[Opensrf-commits] SPAM: r1121 - in branches/autotools: . bin
examples examples/math_xul_client/math/content include/objson
include/opensrf src src/c-apps src/gateway src/java
src/java/org/opensrf src/java/org/opensrf/net/xmpp
src/java/org/opensrf/test src/java/org/opensrf/util
src/javascript src/jserver src/libopensrf src/objson
src/perlmods/OpenSRF src/perlmods/OpenSRF/DomainObject
src/perlmods/OpenSRF/Utils src/python src/python/osrf
src/router src/srfsh
svn at svn.open-ils.org
svn at svn.open-ils.org
Mon Nov 5 08:55:42 EST 2007
Author: asmodai
Date: 2007-11-05 08:40:16 -0500 (Mon, 05 Nov 2007)
New Revision: 1121
Added:
branches/autotools/include/opensrf/osrf_json.h
branches/autotools/include/opensrf/osrf_json_utils.h
branches/autotools/include/opensrf/osrf_json_xml.h
branches/autotools/include/opensrf/osrf_legacy_json.h
branches/autotools/src/java/org/opensrf/test/TestLog.java
branches/autotools/src/java/org/opensrf/test/TestThread.java
branches/autotools/src/java/org/opensrf/util/FileLogger.java
branches/autotools/src/java/org/opensrf/util/Logger.java
branches/autotools/src/javascript/JSON_v0.js
branches/autotools/src/javascript/JSON_v1.js
branches/autotools/src/libopensrf/Makefile.json
branches/autotools/src/libopensrf/osrf_json_object.c
branches/autotools/src/libopensrf/osrf_json_parser.c
branches/autotools/src/libopensrf/osrf_json_test.c
branches/autotools/src/libopensrf/osrf_json_tools.c
branches/autotools/src/libopensrf/osrf_json_xml.c
branches/autotools/src/libopensrf/osrf_legacy_json.c
Removed:
branches/autotools/src/javascript/JSON.js
Modified:
branches/autotools/
branches/autotools/Makefile
branches/autotools/bin/osrf_ctl.sh
branches/autotools/examples/math_xul_client/math/content/math.xul
branches/autotools/examples/opensrf.xml.example
branches/autotools/examples/opensrf_core.xml.example
branches/autotools/examples/srfsh.xml.example
branches/autotools/include/objson/json2xml.h
branches/autotools/include/objson/json_parser.h
branches/autotools/include/objson/object.h
branches/autotools/include/objson/xml2json.h
branches/autotools/include/opensrf/osrfConfig.h
branches/autotools/include/opensrf/osrf_app_session.h
branches/autotools/include/opensrf/osrf_application.h
branches/autotools/include/opensrf/osrf_cache.h
branches/autotools/include/opensrf/osrf_message.h
branches/autotools/include/opensrf/osrf_settings.h
branches/autotools/include/opensrf/string_array.h
branches/autotools/include/opensrf/utils.h
branches/autotools/include/opensrf/xml_utils.h
branches/autotools/install.conf
branches/autotools/src/Makefile
branches/autotools/src/c-apps/Makefile
branches/autotools/src/c-apps/osrf_dbmath.c
branches/autotools/src/c-apps/osrf_math.c
branches/autotools/src/c-apps/osrf_version.c
branches/autotools/src/gateway/Makefile
branches/autotools/src/gateway/apachetools.c
branches/autotools/src/gateway/osrf_json_gateway.c
branches/autotools/src/java/Makefile
branches/autotools/src/java/org/opensrf/ClientSession.java
branches/autotools/src/java/org/opensrf/MethodException.java
branches/autotools/src/java/org/opensrf/Request.java
branches/autotools/src/java/org/opensrf/Session.java
branches/autotools/src/java/org/opensrf/Sys.java
branches/autotools/src/java/org/opensrf/net/xmpp/XMPPReader.java
branches/autotools/src/java/org/opensrf/net/xmpp/XMPPSession.java
branches/autotools/src/java/org/opensrf/test/TestClient.java
branches/autotools/src/java/org/opensrf/util/OSRFObject.java
branches/autotools/src/jserver/Makefile
branches/autotools/src/jserver/osrf_chat.c
branches/autotools/src/libopensrf/Makefile
branches/autotools/src/libopensrf/basic_client.c
branches/autotools/src/libopensrf/log.c
branches/autotools/src/libopensrf/opensrf.c
branches/autotools/src/libopensrf/osrf_app_session.c
branches/autotools/src/libopensrf/osrf_application.c
branches/autotools/src/libopensrf/osrf_cache.c
branches/autotools/src/libopensrf/osrf_hash.c
branches/autotools/src/libopensrf/osrf_message.c
branches/autotools/src/libopensrf/osrf_prefork.c
branches/autotools/src/libopensrf/osrf_settings.c
branches/autotools/src/libopensrf/osrf_stack.c
branches/autotools/src/libopensrf/osrf_system.c
branches/autotools/src/libopensrf/osrf_transgroup.c
branches/autotools/src/libopensrf/sha.c
branches/autotools/src/libopensrf/socket_bundle.c
branches/autotools/src/libopensrf/string_array.c
branches/autotools/src/libopensrf/transport_client.c
branches/autotools/src/libopensrf/transport_message.c
branches/autotools/src/libopensrf/transport_session.c
branches/autotools/src/libopensrf/utils.c
branches/autotools/src/objson/json_parser.c
branches/autotools/src/objson/objson_test.c
branches/autotools/src/perlmods/OpenSRF/AppSession.pm
branches/autotools/src/perlmods/OpenSRF/Application.pm
branches/autotools/src/perlmods/OpenSRF/DomainObject/oilsMessage.pm
branches/autotools/src/perlmods/OpenSRF/DomainObject/oilsResponse.pm
branches/autotools/src/perlmods/OpenSRF/Transport.pm
branches/autotools/src/perlmods/OpenSRF/UnixServer.pm
branches/autotools/src/perlmods/OpenSRF/Utils/JSON.pm
branches/autotools/src/perlmods/OpenSRF/Utils/Logger.pm
branches/autotools/src/python/osrf/gateway.py
branches/autotools/src/python/osrf/json.py
branches/autotools/src/python/osrf/log.py
branches/autotools/src/python/osrf/net.py
branches/autotools/src/python/osrf/net_obj.py
branches/autotools/src/python/osrf/ses.py
branches/autotools/src/python/osrf/stack.py
branches/autotools/src/python/osrf/system.py
branches/autotools/src/python/srfsh.py
branches/autotools/src/router/Makefile
branches/autotools/src/router/osrf_router.c
branches/autotools/src/srfsh/Makefile
branches/autotools/src/srfsh/srfsh.c
Log:
Merged revisions 1045-1120 via svnmerge.
Property changes on: branches/autotools
___________________________________________________________________
Name: svnmerge-integrated
- /trunk:1-1044
+ /trunk:1-1120
Modified: branches/autotools/Makefile
===================================================================
--- branches/autotools/Makefile 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/Makefile 2007-11-05 13:40:16 UTC (rev 1121)
@@ -14,6 +14,9 @@
jserver-install:
source install.conf && make -s -C src jserver-install
+javascript-install:
+ source install.conf && make -s -C src javascript-install
+
clean:
make -s -C src clean
Modified: branches/autotools/bin/osrf_ctl.sh
===================================================================
--- branches/autotools/bin/osrf_ctl.sh 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/bin/osrf_ctl.sh 2007-11-05 13:40:16 UTC (rev 1121)
@@ -12,9 +12,17 @@
function usage {
echo "";
- echo "usage: $0 -d <pid_dir> -c <c_config> -a <action>";
+ echo "usage: $0 [OPTION]... -c <c_config> -a <action>";
echo "";
- echo "Actions include:"
+ echo "Mandatory parameters:";
+ echo -e " -a\t\taction to perform";
+ echo -e " -c\t\tfull path to C configuration file (opensrf_core.xml)";
+ echo "";
+ echo "Optional parameters:";
+ echo -e " -d\t\tstore PID files in this directory";
+ echo -e " -l\t\taccept 'localhost' as the fully-qualified domain name";
+ echo "";
+ echo "Actions include:";
echo -e "\tstart_router"
echo -e "\tstop_router"
echo -e "\trestart_router"
@@ -31,9 +39,10 @@
echo -e "\tstart_all"
echo -e "\trestart_all"
echo "";
- echo "Example:";
- echo " $0 -c opensrf_core.xml -a restart_all";
- echo "";
+ echo "Examples:";
+ echo " $0 -c opensrf_core.xml -a restart_all";
+ echo " $0 -l -c opensrf_core.xml -a restart_all";
+ echo "";
exit;
}
@@ -41,11 +50,12 @@
# ---------------------------------------------------------------------------
# Load the command line options and set the global vars
# ---------------------------------------------------------------------------
-while getopts "c:a:d:h" flag; do
+while getopts "c:a:d:lh" flag; do
case $flag in
"a") OPT_ACTION="$OPTARG";;
"c") OPT_CONFIG="$OPTARG";;
"d") OPT_PID_DIR="$OPTARG";;
+ "l") export OSRF_HOSTNAME="localhost";;
"h"|*) usage;;
esac;
done
Modified: branches/autotools/examples/math_xul_client/math/content/math.xul
===================================================================
--- branches/autotools/examples/math_xul_client/math/content/math.xul 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/examples/math_xul_client/math/content/math.xul 2007-11-05 13:40:16 UTC (rev 1121)
@@ -16,7 +16,7 @@
<!-- OpenSRF -->
<script>var myPackageDir = "math";</script>
- <script src="OpenSRF/JSON.js" />
+ <script src="OpenSRF/JSON_v1.js" />
<script src="OpenSRF/md5.js" />
<script src="OpenSRF/opensrf_utils.js" />
<script src="OpenSRF/opensrf_config.js" />
Modified: branches/autotools/examples/opensrf.xml.example
===================================================================
--- branches/autotools/examples/opensrf.xml.example 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/examples/opensrf.xml.example 2007-11-05 13:40:16 UTC (rev 1121)
@@ -175,7 +175,7 @@
<hosts>
- <myhost.mydomain.org>
+ <localhost>
<!-- ^-=-
Must match the fully qualified domain name of the host
on Linux, this is usually the output of "hostname -f"
@@ -200,7 +200,7 @@
</apps>
- </myhost.mydomain.org>
+ </localhost>
</hosts>
Modified: branches/autotools/examples/opensrf_core.xml.example
===================================================================
--- branches/autotools/examples/opensrf_core.xml.example 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/examples/opensrf_core.xml.example 2007-11-05 13:40:16 UTC (rev 1121)
@@ -80,11 +80,6 @@
-->
<services>
<service>opensrf.math</service>
- <service>open-ils.cat</service>
- <service>open-ils.search</service>
- <service>open-ils.circ</service>
- <service>open-ils.actor</service>
- <service>open-ils.auth</service>
</services>
<!-- jabber login info -->
Modified: branches/autotools/examples/srfsh.xml.example
===================================================================
--- branches/autotools/examples/srfsh.xml.example 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/examples/srfsh.xml.example 2007-11-05 13:40:16 UTC (rev 1121)
@@ -3,7 +3,7 @@
<srfsh>
<router_name>router</router_name>
<domains>
- <domain>127.0.0.1</domain>
+ <domain>localhost</domain>
</domains>
<username>myusername</username>
<passwd>mypassword</passwd>
Modified: branches/autotools/include/objson/json2xml.h
===================================================================
--- branches/autotools/include/objson/json2xml.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/objson/json2xml.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,11 +1,10 @@
+/*
+ * Header to support legacy objson library
+ */
+#ifndef OBJSON_JSON2XML_H
+#define OBJSON_JSON2XML_H
+#include <opensrf/osrf_json.h>
+#include <opensrf/osrf_json_xml.h>
+#include <opensrf/osrf_legacy_json.h>
+#endif
-#include <string.h>
-#include <stdio.h>
-
-/* the JSON parser, so we can read the response we're XMLizing */
-#include <objson/object.h>
-#include <objson/json_parser.h>
-#include <opensrf/utils.h>
-
-char* jsonObjectToXML(jsonObject*);
-
Modified: branches/autotools/include/objson/json_parser.h
===================================================================
--- branches/autotools/include/objson/json_parser.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/objson/json_parser.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,84 +1,9 @@
/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <highfalutin at gmail.com>
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-*/
-
-
-
-
-/* ---------------------------------------------------------------------------------------
- JSON parser.
- * --------------------------------------------------------------------------------------- */
-#ifndef JSON_PARSER_H
-#define JSON_PARSER_H
-
-#include <stdio.h>
-#include <ctype.h>
-#include <objson/object.h>
-#include <opensrf/utils.h>
-
-
-
-/* Parses the given JSON string and returns the built object.
- * returns NULL (and prints parser error to stderr) on error.
+ * Header to support legacy objson library
*/
-
-jsonObject* json_parse_string(char* string);
-
-jsonObject* jsonParseString(char* string);
-jsonObject* jsonParseStringFmt( char* string, ... );
-
-jsonObject* json_parse_file( const char* filename );
-
-jsonObject* jsonParseFile( const char* string );
-
-
-
-/* does the actual parsing work. returns 0 on success. -1 on error and
- * -2 if there was no object to build (string was all comments)
- */
-int _json_parse_string(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-/* returns 0 on success and turns obj into a string object */
-int json_parse_json_string(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-/* returns 0 on success and turns obj into a number or double object */
-int json_parse_json_number(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-/* returns 0 on success and turns obj into an 'object' object */
-int json_parse_json_object(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-/* returns 0 on success and turns object into an array object */
-int json_parse_json_array(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-/* churns through whitespace and increments index as it goes.
- * eat_all == true means we should eat newlines, tabs
- */
-void json_eat_ws(char* string, unsigned long* index, int eat_all, int current_strlen);
-
-int json_parse_json_bool(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-/* removes comments from a json string. if the comment contains a class hint
- * and class_hint isn't NULL, an allocated char* with the class name will be
- * shoved into *class_hint. returns 0 on success, -1 on parse error.
- * 'index' is assumed to be at the second character (*) of the comment
- */
-int json_eat_comment(char* string, unsigned long* index, char** class_hint, int parse_class, int current_strlen);
-
-/* prints a useful error message to stderr. always returns -1 */
-int json_handle_error(char* string, unsigned long* index, char* err_msg);
-
-int json_parse_json_null(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-
+#ifndef OBJSON_XML2JSON_H
+#define OBJSON_XML2JSON_H
+#include <opensrf/osrf_json.h>
+#include <opensrf/osrf_json_xml.h>
+#include <opensrf/osrf_legacy_json.h>
#endif
Modified: branches/autotools/include/objson/object.h
===================================================================
--- branches/autotools/include/objson/object.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/objson/object.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,286 +1,8 @@
/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <highfalutin at gmail.com>
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-*/
-
-
-/* ---------------------------------------------------------------------------------------
- libjson
- * --------------------------------------------------------------------------------------- */
-
-#ifndef _JSON_OBJECT_H
-#define _JSON_OBJECT_H
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <opensrf/utils.h>
-
-/* json object types */
-#define JSON_HASH 0
-#define JSON_ARRAY 1
-#define JSON_STRING 2
-#define JSON_NUMBER 3
-#define JSON_NULL 4
-#define JSON_BOOL 5
-
-
-/* top level generic object structure */
-struct _jsonObjectStruct {
-
- /* how many sub-objects do we contain if we're an array or an object.
- Note that this includes null array elements in sparse arrays */
- unsigned long size;
-
- /* optional class hint */
- char* classname;
-
- /* see JSON types above */
- int type;
-
-
- /* our cargo */
- union _jsonObjectValue {
- struct _jsonObjectNodeStruct* c; /* our list of sub-objects if we're an array or a hash */
- char* s; /* string */
- int b; /* bool */
- double n; /* number */
- } value;
-
-
- /* client may provide a comment string which will be
- * added to the object when stringified */
- char* comment;
-
-};
-typedef struct _jsonObjectStruct jsonObject;
-
-
-/**
- String parsing function. This is assigned by the json_parser code.
- to avoid circular dependency, declare the parse function here,
- and have the json parse code set the variable to a real function
-*/
-//jsonObject* (*jsonParseString) (char* str);
-
-
-/* this contains a single element of the object along with the elements
- * index (if this object is an array) and key (if this object is a hash)
+ * Header to support legacy objson library
*/
-struct _jsonObjectNodeStruct {
-
- unsigned long index; /* our array position */
- char* key; /* our hash key */
-
- jsonObject* item; /* our object */
- struct _jsonObjectNodeStruct* next; /* pointer to the next object node */
-};
-typedef struct _jsonObjectNodeStruct jsonObjectNode;
-
-
-
-/* utility object for iterating over hash objects */
-struct _jsonObjectIteratorStruct {
- const jsonObject* obj; /* the topic object */
- jsonObjectNode* current; /* the current node within the object */
-};
-typedef struct _jsonObjectIteratorStruct jsonObjectIterator;
-
-
-/** Allocates a new iterator
- @param obj The object over which to iterate.
-*/
-jsonObjectIterator* jsonNewObjectIterator(const jsonObject* obj);
-
-/**
- De-allocates an iterator
- @param iter The iterator object to free
-*/
-void jsonObjectIteratorFree(jsonObjectIterator* iter);
-
-/**
- Returns the object_node currently pointed to by the iterator
- and increments the pointer to the next node
- @param iter The iterator in question.
- */
-jsonObjectNode* jsonObjectIteratorNext(jsonObjectIterator* iter);
-
-/**
- @param iter The iterator.
- @return True if there is another node after the current node.
- */
-int jsonObjectIteratorHasNext(const jsonObjectIterator* iter);
-
-
-/**
- Allocates a new object.
- @param string The string data if this object is to be a string.
- if not, string should be NULL
- @return The newly allocated object or NULL on memory error.
-*/
-jsonObject* jsonNewObjectFmt(const char* string, ...);
-jsonObject* jsonNewObject(const char* string);
-
-/**
- Allocates a new JSON number object.
- @param num The number this object is to hold
- @return The newly allocated object.
-*/
-jsonObject* jsonNewNumberObject( double num );
-
-
-/**
- Returns a pointer to the object at the given index. This call is
- only valid if the object has a type of JSON_ARRAY.
- @param obj The object
- @param index The position within the object
- @return The object at the given index.
-*/
-jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index );
-
-
-/**
- Returns a pointer to the object with the given key
- @param obj The object
- @param key The key
- @return The object with the given key.
-*/
-jsonObject* jsonObjectGetKey( const jsonObject* obj, const char* key );
-
-/**
- De-allocates an object. Note that this function should only be called
- on objects that are _not_ children of other objects or there will be
- double-free's
- @param obj The object to free.
-*/
-void jsonObjectFree(jsonObject* obj);
-
-
-/**
- Allocates a new object node.
- @param obj The object to which the node will be appended.
- @return The new object node.
-*/
-jsonObjectNode* jsonNewObjectNode(jsonObject* obj);
-
-/**
- De-allocates an object node
- @param obj The object node to de-allocate.
-*/
-void jsonObjectNodeFree(jsonObjectNode* obj);
-
-
-/**
- Pushes the given object onto the end of the list. This coerces an object
- into becoming an array. _Only_ use this function on objects that you
- want to become an array.
- If obj is NULL, inserts a new NULL object into the list.
- @return array size on success, -1 on error
- */
-unsigned long jsonObjectPush(jsonObject* dest, jsonObject* newObj);
-
-/* removes (and deallocates) the object at the given index (if one exists) and inserts
- * the new one. returns the size on success, -1 on error
- * If obj is NULL, inserts a new object into the list with is_null set to true
- */
-unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj);
-
-/* inserts the new object, overwriting (removing, deallocating) any
- * previous object with the given key.
- * returns the size on success, -1 on error
- * if 'obj' is NULL, a new object is inserted at key 'key' with 'is_null'
- * set to true
- */
-unsigned long jsonObjectSetKey(jsonObject* dest, const char* key, jsonObject* newObj);
-
-/* removes the object at the given index and, if more items exist,
- * re-indexes (shifts down by 1) the rest of the objects in the array
- */
-unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index);
-
-/* removes (and deallocates) the object with key 'key' if it exists */
-unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key);
-
-/* returns a pointer to the string data held by this object if this object
- is a string. Otherwise returns NULL*/
-char* jsonObjectGetString(const jsonObject*);
-
-double jsonObjectGetNumber( const jsonObject* obj );
-
-/* sets the string data */
-void jsonObjectSetString(jsonObject* dest, const char* string);
-
-/* sets the number value for the object */
-void jsonObjectSetNumber(jsonObject* dest, double num);
-
-/* sets the class hint for this object */
-void jsonObjectSetClass(jsonObject* dest, const char* classname );
-
-/* converts an object to a json string. client is responsible for freeing the return string */
-char* jsonObjectToJSON( const jsonObject* obj );
-
-/* set this object's comment string */
-void jsonObjectSetComment(jsonObject* dest, const char* classname);
-
-/* utility method. starting at index 'index', shifts all indices down by one and
- * decrements the objects size by 1
- */
-void _jsonObjectShiftIndex(jsonObject* dest, unsigned long index);
-
-/* formats a JSON string from printing. User must free returned string */
-char* jsonFormatString( const char* jsonString );
-
-jsonObject* jsonObjectClone( const jsonObject* o );
-
-/* tries to extract the string data from an object.
- if object -> NULL (the C NULL)
- if array -> NULL (the C NULL)
- if null -> NULL (the C NULL)
- if true/false -> true/false
- if string/number/double the string version of either of those
- The caller is responsible for freeing the returned string
- */
-char* jsonObjectToSimpleString( const jsonObject* o );
-
-int jsonBoolIsTrue( const jsonObject* o );
-
-
-/* ------------------------------------------------------------------------ */
-/* XPATH */
-
-/* provides an XPATH style search interface (e.g. /some/node/here) and
- return the object at that location if one exists. Naturally,
- every element in the path must be a proper object ("hash" / {}).
- Returns NULL if the specified node is not found
- Note also that the object returned is a clone and
- must be freed by the caller
-*/
-jsonObject* jsonObjectFindPath( const jsonObject* obj, char* path, ... );
-
-
-/* Utility method. finds any object in the tree that matches the path.
- Use this for finding paths that start with '//' */
-jsonObject* _jsonObjectFindPathRecurse( const jsonObject* o, char* root, char* path );
-
-/* returns a list of object whose key is 'root'. These are used as
- potential objects when doing a // search */
-jsonObject* __jsonObjectFindPathRecurse( const jsonObject* o, char* root );
-
-/* ------------------------------------------------------------------------ */
-
-
+#ifndef OBJSON_OBJECT_H
+#define OBJSON_OBJECT_H
+#include <opensrf/osrf_json.h>
+#include <opensrf/osrf_legacy_json.h>
#endif
-
-
Modified: branches/autotools/include/objson/xml2json.h
===================================================================
--- branches/autotools/include/objson/xml2json.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/objson/xml2json.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,19 +1,11 @@
+/*
+ * Header to support legacy objson library
+ */
+#ifndef OBJSON_XML2JSON_H
+#define OBJSON_XML2JSON_H
+#include <opensrf/osrf_json.h>
+#include <opensrf/osrf_json_xml.h>
+#include <opensrf/osrf_legacy_json.h>
+#endif
-#include <stdio.h>
-#include <string.h>
-#include <libxml/globals.h>
-#include <libxml/xmlerror.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlmemory.h>
-#include <objson/object.h>
-#include <objson/json_parser.h>
-#include <opensrf/utils.h>
-#include <opensrf/osrf_list.h>
-
-
-jsonObject* jsonXMLToJSONObject(const char* xml);
-
-
-
Modified: branches/autotools/include/opensrf/osrfConfig.h
===================================================================
--- branches/autotools/include/opensrf/osrfConfig.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/opensrf/osrfConfig.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -19,7 +19,7 @@
#include <opensrf/xml_utils.h>
#include <opensrf/utils.h>
#include <opensrf/string_array.h>
-#include <objson/object.h>
+#include <opensrf/osrf_json.h>
typedef struct {
jsonObject* config;
Modified: branches/autotools/include/opensrf/osrf_app_session.h
===================================================================
--- branches/autotools/include/opensrf/osrf_app_session.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/opensrf/osrf_app_session.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -9,8 +9,7 @@
#include <opensrf/osrf_hash.h>
#include <opensrf/osrf_list.h>
-#include <objson/object.h>
-#include <objson/json_parser.h>
+#include <opensrf/osrf_json.h>
@@ -76,6 +75,9 @@
/** 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;
@@ -100,6 +102,9 @@
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 );
@@ -115,6 +120,14 @@
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 );
Modified: branches/autotools/include/opensrf/osrf_application.h
===================================================================
--- branches/autotools/include/opensrf/osrf_application.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/opensrf/osrf_application.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -3,7 +3,7 @@
#include <opensrf/osrf_app_session.h>
#include <opensrf/osrf_hash.h>
-#include <objson/object.h>
+#include <opensrf/osrf_json.h>
#include <stdio.h>
#include <dlfcn.h>
Modified: branches/autotools/include/opensrf/osrf_cache.h
===================================================================
--- branches/autotools/include/opensrf/osrf_cache.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/opensrf/osrf_cache.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -14,8 +14,7 @@
*/
-#include <objson/object.h>
-#include <objson/json_parser.h>
+#include <opensrf/osrf_json.h>
#include <memcache.h>
#include <opensrf/log.h>
@@ -81,3 +80,7 @@
+/**
+ * Clean up the global cache handles, etc.
+ */
+void osrfCacheCleanup();
Copied: branches/autotools/include/opensrf/osrf_json.h (from rev 1120, trunk/include/opensrf/osrf_json.h)
===================================================================
--- branches/autotools/include/opensrf/osrf_json.h (rev 0)
+++ branches/autotools/include/opensrf/osrf_json.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,381 @@
+/*
+Copyright (C) 2006 Georgia Public Library Service
+Bill Erickson <billserickson at gmail.com>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+*/
+
+
+#include <opensrf/utils.h>
+#include <opensrf/osrf_list.h>
+#include <opensrf/osrf_hash.h>
+
+#ifndef _JSON_H
+#define _JSON_H
+
+
+/* parser states */
+#define JSON_STATE_IN_OBJECT 0x1
+#define JSON_STATE_IN_ARRAY 0x2
+#define JSON_STATE_IN_STRING 0x4
+#define JSON_STATE_IN_UTF 0x8
+#define JSON_STATE_IN_ESCAPE 0x10
+#define JSON_STATE_IN_KEY 0x20
+#define JSON_STATE_IN_NULL 0x40
+#define JSON_STATE_IN_TRUE 0x80
+#define JSON_STATE_IN_FALSE 0x100
+#define JSON_STATE_IN_NUMBER 0x200
+#define JSON_STATE_IS_INVALID 0x400
+#define JSON_STATE_IS_DONE 0x800
+#define JSON_STATE_START_COMMEN 0x1000
+#define JSON_STATE_IN_COMMENT 0x2000
+#define JSON_STATE_END_COMMENT 0x4000
+
+
+/* object and array (container) states are pushed onto a stack so we
+ * can keep track of the object nest. All other states are
+ * simply stored in the state field of the parser */
+#define JSON_STATE_SET(ctx,s) ctx->state |= s; /* set a state */
+#define JSON_STATE_REMOVE(ctx,s) ctx->state &= ~s; /* unset a state */
+#define JSON_STATE_CHECK(ctx,s) (ctx->state & s) ? 1 : 0 /* check if a state is set */
+#define JSON_STATE_POP(ctx) osrfListPop( ctx->stateStack ); /* remove a state from the stack */
+#define JSON_STATE_PUSH(ctx, state) osrfListPush( ctx->stateStack,(void*) state );/* push a state on the stack */
+#define JSON_STATE_PEEK(ctx) osrfListGetIndex(ctx->stateStack, ctx->stateStack->size -1) /* check which container type we're currently in */
+#define JSON_STATE_CHECK_STACK(ctx, s) (JSON_STATE_PEEK(ctx) == (void*) s ) ? 1 : 0 /* compare stack values */
+
+/* JSON types */
+#define JSON_HASH 0
+#define JSON_ARRAY 1
+#define JSON_STRING 2
+#define JSON_NUMBER 3
+#define JSON_NULL 4
+#define JSON_BOOL 5
+
+#define JSON_PARSE_LAST_CHUNK 0x1 /* this is the last part of the string we're parsing */
+
+#define JSON_PARSE_FLAG_CHECK(ctx, f) (ctx->flags & f) ? 1 : 0 /* check if a parser state is set */
+
+#ifndef JSON_CLASS_KEY
+#define JSON_CLASS_KEY "__c"
+#endif
+#ifndef JSON_DATA_KEY
+#define JSON_DATA_KEY "__p"
+#endif
+
+
+struct jsonParserContextStruct {
+ int state; /* what are we currently parsing */
+ const char* chunk; /* the chunk we're currently parsing */
+ int index; /* where we are in parsing the current chunk */
+ int chunksize; /* the size of the current chunk */
+ int flags; /* parser flags */
+ osrfList* stateStack; /* represents the nest of object/array states */
+ growing_buffer* buffer; /* used to hold JSON strings, number, true, false, and null sequences */
+ growing_buffer* utfbuf; /* holds the current unicode characters */
+ void* userData; /* opaque user pointer. we ignore this */
+ struct jsonParserHandlerStruct* handler; /* the event handler struct */
+};
+typedef struct jsonParserContextStruct jsonParserContext;
+
+struct jsonParserHandlerStruct {
+ void (*handleStartObject) (void* userData);
+ void (*handleObjectKey) (void* userData, char* key);
+ void (*handleEndObject) (void* userData);
+ void (*handleStartArray) (void* userData);
+ void (*handleEndArray) (void* userData);
+ void (*handleNull) (void* userData);
+ void (*handleString) (void* userData, char* string);
+ void (*handleBool) (void* userData, int boolval);
+ void (*handleNumber) (void* userData, double num);
+ void (*handleError) (void* userData, char* err, ...);
+};
+typedef struct jsonParserHandlerStruct jsonParserHandler;
+
+struct _jsonObjectStruct {
+ unsigned long size; /* number of sub-items */
+ char* classname; /* optional class hint (not part of the JSON spec) */
+ int type; /* JSON type */
+ struct _jsonObjectStruct* parent; /* who we're attached to */
+ union __jsonValue { /* cargo */
+ osrfHash* h; /* object container */
+ osrfList* l; /* array container */
+ char* s; /* string */
+ int b; /* bool */
+// double n; /* number */
+ double n; /* number */
+ } value;
+};
+typedef struct _jsonObjectStruct jsonObject;
+
+struct _jsonIteratorStruct {
+ jsonObject* obj; /* the object we're traversing */
+ osrfHashIterator* hashItr; /* the iterator for this hash */
+ char* key; /* if this object is an object, the current key */
+ unsigned long index; /* if this object is an array, the index */
+};
+typedef struct _jsonIteratorStruct jsonIterator;
+
+
+
+/**
+ * Allocates a new parser context object
+ * @param handler The event handler struct
+ * @param userData Opaque user pointer which is available in callbacks
+ * and ignored by the parser
+ * @return An allocated parser context, NULL on error
+ */
+jsonParserContext* jsonNewParser( jsonParserHandler* handler, void* userData);
+
+/**
+ * Deallocates a parser context
+ * @param ctx The context object
+ */
+void jsonParserFree( jsonParserContext* ctx );
+
+/**
+ * Parse a chunk of data.
+ * @param ctx The parser context
+ * @param data The data to parse
+ * @param datalen The size of the chunk to parser
+ * @param flags Reserved
+ */
+int jsonParseChunk( jsonParserContext* ctx, const char* data, int datalen, int flags );
+
+
+/**
+ * Parses a JSON string;
+ * @param str The string to parser
+ * @return The resulting JSON object or NULL on error
+ */
+jsonObject* jsonParseString( const char* str );
+jsonObject* jsonParseStringRaw( const char* str );
+
+jsonObject* jsonParseStringFmt( const char* str, ... );
+
+/**
+ * Parses a JSON string;
+ * @param str The string to parser
+ * @return The resulting JSON object or NULL on error
+ */
+jsonObject* jsonParseStringHandleError( void (*errorHandler) (const char*), char* str, ... );
+
+
+
+/**
+ * Creates a new json object
+ * @param data The string data this object will hold if
+ * this object happens to be a JSON_STRING, NULL otherwise
+ * @return The allocated json object. Must be freed with
+ * jsonObjectFree()
+ */
+jsonObject* jsonNewObject(const char* data);
+jsonObject* jsonNewObjectFmt(const char* data, ...);
+
+/**
+ * Creates a new object of the given type
+ */
+jsonObject* jsonNewObjectType(int type);
+
+/**
+ * Creates a new number object
+ */
+jsonObject* jsonNewNumberObject( double num );
+
+
+/**
+ * Creates a new json bool
+ */
+jsonObject* jsonNewBoolObject(int val);
+
+/**
+ * Deallocates an object
+ */
+void jsonObjectFree( jsonObject* o );
+
+/**
+ * Forces the given object to become an array (if it isn't already one)
+ * and pushes the new object into the array
+ */
+unsigned long jsonObjectPush(jsonObject* o, jsonObject* newo);
+
+/**
+ * Forces the given object to become a hash (if it isn't already one)
+ * and assigns the new object to the key of the hash
+ */
+unsigned long jsonObjectSetKey(
+ jsonObject* o, const char* key, jsonObject* newo);
+
+
+/**
+ * Turns the object into a JSON string. The string must be freed by the caller */
+char* jsonObjectToJSON( const jsonObject* obj );
+char* jsonObjectToJSONRaw( const jsonObject* obj );
+
+
+/**
+ * Retrieves the object at the given key
+ */
+jsonObject* jsonObjectGetKey( const jsonObject* obj, const char* key );
+const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key );
+
+
+
+
+
+/** Allocates a new iterator
+ @param obj The object over which to iterate.
+*/
+jsonIterator* jsonNewIterator(const jsonObject* obj);
+
+
+/**
+ De-allocates an iterator
+ @param iter The iterator object to free
+*/
+void jsonIteratorFree(jsonIterator* iter);
+
+/**
+ Returns the object_node currently pointed to by the iterator
+ and increments the pointer to the next node
+ @param iter The iterator in question.
+ */
+jsonObject* jsonIteratorNext(jsonIterator* iter);
+
+
+/**
+ @param iter The iterator.
+ @return True if there is another node after the current node.
+ */
+int jsonIteratorHasNext(const jsonIterator* iter);
+
+
+/**
+ Returns a pointer to the object at the given index. This call is
+ only valid if the object has a type of JSON_ARRAY.
+ @param obj The object
+ @param index The position within the object
+ @return The object at the given index.
+*/
+jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index );
+
+
+/* removes (and deallocates) the object at the given index (if one exists) and inserts
+ * the new one. returns the size on success, -1 on error
+ * If obj is NULL, inserts a new object into the list with is_null set to true
+ */
+unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj);
+
+/* removes the object at the given index and, if more items exist,
+ * re-indexes (shifts down by 1) the rest of the objects in the array
+ */
+unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index);
+
+/* removes (and deallocates) the object with key 'key' if it exists */
+unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key);
+
+/* returns a pointer to the string data held by this object if this object
+ is a string. Otherwise returns NULL*/
+char* jsonObjectGetString(const jsonObject*);
+
+double jsonObjectGetNumber( const jsonObject* obj );
+
+/* sets the string data */
+void jsonObjectSetString(jsonObject* dest, const char* string);
+
+/* sets the number value for the object */
+void jsonObjectSetNumber(jsonObject* dest, double num);
+
+/* sets the class hint for this object */
+void jsonObjectSetClass(jsonObject* dest, const char* classname );
+const char* jsonObjectGetClass(const jsonObject* dest);
+
+int jsonBoolIsTrue( jsonObject* boolObj );
+
+void jsonSetBool(jsonObject* bl, int val);
+
+jsonObject* jsonObjectClone( const jsonObject* o );
+
+
+/* tries to extract the string data from an object.
+ if object -> NULL (the C NULL)
+ if array -> NULL
+ if null -> NULL
+ if bool -> NULL
+ if string/number the string version of either of those
+ The caller is responsible for freeing the returned string
+ */
+char* jsonObjectToSimpleString( const jsonObject* o );
+
+
+
+/* provides an XPATH style search interface (e.g. /some/node/here) and
+ return the object at that location if one exists. Naturally,
+ every element in the path must be a proper object ("hash" / {}).
+ Returns NULL if the specified node is not found
+ Note also that the object returned is a clone and
+ must be freed by the caller
+*/
+jsonObject* jsonObjectFindPath( const jsonObject* obj, char* path, ... );
+
+
+/* formats a JSON string from printing. User must free returned string */
+char* jsonFormatString( const char* jsonString );
+
+/* sets the error handler for all parsers */
+void jsonSetGlobalErrorHandler(void (*errorHandler) (const char*));
+
+jsonObject* jsonParseFile( char* filename );
+
+/* ------------------------------------------------------------------------- */
+/**
+ * The following methods provide a facility for serializing and
+ * deserializing "classed" JSON objects. To give a JSON object a
+ * class, simply call jsonObjectSetClass().
+ * Then, calling jsonObjectEncodeClass() will convert the JSON
+ * object (and any sub-objects) to a JSON object with class
+ * wrapper objects like so:
+ * { _c : "classname", _d : <json_thing> }
+ * In this example _c is the class key and _d is the data (object)
+ * key. The keys are defined by the constants
+ * OSRF_JSON_CLASS_KEY and OSRF_JSON_DATA_KEY
+ * To revive a serialized object, simply call
+ * jsonObjectDecodeClass()
+ */
+
+
+/** Converts a class-wrapped object into an object with the
+ * classname set
+ * Caller must free the returned object
+ */
+jsonObject* jsonObjectDecodeClass( const jsonObject* obj );
+
+
+/** Converts an object with a classname into a
+ * class-wrapped (serialized) object
+ * Caller must free the returned object
+ */
+jsonObject* jsonObjectEncodeClass( const jsonObject* obj );
+
+/* ------------------------------------------------------------------------- */
+
+
+/**
+ * Generates an XML representation of a JSON object */
+char* jsonObjectToXML(jsonObject*);
+
+
+/*
+ * Builds a JSON object from the provided XML
+ */
+jsonObject* jsonXMLToJSONObject(const char* xml);
+
+
+#endif
Copied: branches/autotools/include/opensrf/osrf_json_utils.h (from rev 1120, trunk/include/opensrf/osrf_json_utils.h)
===================================================================
--- branches/autotools/include/opensrf/osrf_json_utils.h (rev 0)
+++ branches/autotools/include/opensrf/osrf_json_utils.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,107 @@
+/*
+Copyright (C) 2006 Georgia Public Library Service
+Bill Erickson <billserickson at gmail.com>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+*/
+
+
+/* ----------------------------------------------------------------------- */
+/* Clients need not include this file. These are internal utilities only */
+/* ----------------------------------------------------------------------- */
+
+#define JSON_EAT_WS(ctx) \
+ while( ctx->index < ctx->chunksize ) { \
+ if(!isspace(ctx->chunk[ctx->index])) break; \
+ ctx->index++; \
+ } \
+ if( ctx->index >= ctx->chunksize ) return 0; \
+ c = ctx->chunk[ctx->index];
+
+#define JSON_CACHE_DATA(ctx, buf, size) \
+ while( (buf->n_used < size) && (ctx->index < ctx->chunksize) ) \
+ buffer_add_char(buf, ctx->chunk[ctx->index++]);
+
+#define JSON_LOG_MARK __FILE__,__LINE__
+
+#define JSON_NUMBER_CHARS "0123456789.+-e"
+
+/**
+ * These are the callbacks through which the top level parser
+ * builds objects via the push parser
+ */
+void _jsonHandleStartObject(void*);
+void _jsonHandleObjectKey(void*, char* key);
+void _jsonHandleEndObject(void*);
+void _jsonHandleStartArray(void*);
+void _jsonHandleEndArray(void*);
+void _jsonHandleNull(void*);
+void _jsonHandleString(void*, char* string);
+void _jsonHandleBool(void*, int boolval);
+void _jsonHandleNumber(void*, double num);
+void _jsonHandleError(void*, char* str, ...);
+
+struct jsonInternalParserStruct {
+ jsonParserContext* ctx;
+ jsonObject* obj;
+ jsonObject* current;
+ char* lastkey;
+ void (*handleError) (const char*);
+};
+typedef struct jsonInternalParserStruct jsonInternalParser;
+
+jsonInternalParser* _jsonNewInternalParser();
+void _jsonInternalParserFree(jsonInternalParser* p);
+
+/**
+ * Calls the defined error handler with the given error message.
+ * @return -1
+ */
+int _jsonParserError( jsonParserContext* ctx, char* err, ... );
+
+
+/**
+ *
+ * @return 0 on continue, 1 if it goes past the end of the string, -1 on error
+ */
+int _jsonParserHandleUnicode( jsonParserContext* ctx );
+
+
+/**
+ * @param type 0 for null, 1 for true, 2 for false
+ * @return 0 on continue, 1 if it goes past the end of the string, -1 on error
+ */
+int _jsonParserHandleMatch( jsonParserContext* ctx, int type );
+
+/**
+ * @return 0 on continue, 1 on end of chunk, -1 on error
+ */
+int _jsonParserHandleString( jsonParserContext* ctx );
+
+/**
+ * @return 0 on continue, 1 on end of chunk, -1 on error
+ */
+int _jsonParserHandleNumber( jsonParserContext* ctx );
+
+
+void _jsonInsertParserItem( jsonInternalParser* p, jsonObject* newo );
+
+
+/* Utility method. finds any object in the tree that matches the path.
+ Use this for finding paths that start with '//' */
+jsonObject* _jsonObjectFindPathRecurse( const jsonObject* o, char* root, char* path );
+
+
+/* returns a list of object whose key is 'root'. These are used as
+ potential objects when doing a // search */
+jsonObject* __jsonObjectFindPathRecurse( const jsonObject* o, char* root );
+
+
Copied: branches/autotools/include/opensrf/osrf_json_xml.h (from rev 1120, trunk/include/opensrf/osrf_json_xml.h)
===================================================================
--- branches/autotools/include/opensrf/osrf_json_xml.h (rev 0)
+++ branches/autotools/include/opensrf/osrf_json_xml.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,26 @@
+#ifdef OSRF_JSON_ENABLE_XML_UTILS
+
+#include <stdio.h>
+#include <string.h>
+#include <libxml/globals.h>
+#include <libxml/xmlerror.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+
+#include <opensrf/osrf_json.h>
+#include <opensrf/utils.h>
+#include <opensrf/osrf_list.h>
+
+
+/**
+ * Generates an XML representation of a JSON object */
+char* jsonObjectToXML(jsonObject*);
+
+
+/*
+ * Builds a JSON object from the provided XML
+ */
+jsonObject* jsonXMLToJSONObject(const char* xml);
+
+#endif
Copied: branches/autotools/include/opensrf/osrf_legacy_json.h (from rev 1120, trunk/include/opensrf/osrf_legacy_json.h)
===================================================================
--- branches/autotools/include/opensrf/osrf_legacy_json.h (rev 0)
+++ branches/autotools/include/opensrf/osrf_legacy_json.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,135 @@
+/*
+Copyright (C) 2005 Georgia Public Library Service
+Bill Erickson <highfalutin at gmail.com>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+*/
+
+
+
+
+/* ---------------------------------------------------------------------------------------
+ JSON parser.
+ * --------------------------------------------------------------------------------------- */
+#ifndef LEGACY_JSON_H
+#define LEGACY_JSON_H
+
+#include <opensrf/osrf_json.h>
+#include <ctype.h>
+
+
+
+/* Parses the given JSON string and returns the built object.
+ * returns NULL (and prints parser error to stderr) on error.
+ */
+
+jsonObject* json_parse_string(char* string);
+
+jsonObject* legacy_jsonParseString(const char* string);
+jsonObject* legacy_jsonParseStringFmt( const char* string, ... );
+
+jsonObject* json_parse_file( const char* filename );
+
+jsonObject* legacy_jsonParseFile( const char* string );
+
+
+
+/* does the actual parsing work. returns 0 on success. -1 on error and
+ * -2 if there was no object to build (string was all comments)
+ */
+int _json_parse_string(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
+
+/* returns 0 on success and turns obj into a string object */
+int json_parse_json_string(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
+
+/* returns 0 on success and turns obj into a number or double object */
+int json_parse_json_number(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
+
+/* returns 0 on success and turns obj into an 'object' object */
+int json_parse_json_object(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
+
+/* returns 0 on success and turns object into an array object */
+int json_parse_json_array(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
+
+/* churns through whitespace and increments index as it goes.
+ * eat_all == true means we should eat newlines, tabs
+ */
+void json_eat_ws(char* string, unsigned long* index, int eat_all, int current_strlen);
+
+int json_parse_json_bool(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
+
+/* removes comments from a json string. if the comment contains a class hint
+ * and class_hint isn't NULL, an allocated char* with the class name will be
+ * shoved into *class_hint. returns 0 on success, -1 on parse error.
+ * 'index' is assumed to be at the second character (*) of the comment
+ */
+int json_eat_comment(char* string, unsigned long* index, char** class_hint, int parse_class, int current_strlen);
+
+/* prints a useful error message to stderr. always returns -1 */
+int json_handle_error(char* string, unsigned long* index, char* err_msg);
+
+int json_parse_json_null(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
+
+
+char* legacy_jsonObjectToJSON( const jsonObject* obj );
+
+
+
+/* LEGACY ITERATOR CODE ---------------------------------------------------
+ ------------------------------------------------------------------------ */
+
+struct _jsonObjectNodeStruct {
+ unsigned long index; /* our array position */
+ char* key; /* our hash key */
+ jsonObject* item; /* our object */
+};
+typedef struct _jsonObjectNodeStruct jsonObjectNode;
+
+
+
+/* utility object for iterating over hash objects */
+struct _jsonObjectIteratorStruct {
+ jsonIterator* iterator;
+ const jsonObject* obj; /* the topic object */
+ jsonObjectNode* current; /* the current node within the object */
+ int done;
+};
+typedef struct _jsonObjectIteratorStruct jsonObjectIterator;
+
+
+/** Allocates a new iterator
+ @param obj The object over which to iterate.
+*/
+jsonObjectIterator* jsonNewObjectIterator(const jsonObject* obj);
+
+/**
+ De-allocates an iterator
+ @param iter The iterator object to free
+*/
+void jsonObjectIteratorFree(jsonObjectIterator* iter);
+
+/**
+ Returns the object_node currently pointed to by the iterator
+ and increments the pointer to the next node
+ @param iter The iterator in question.
+ */
+jsonObjectNode* jsonObjectIteratorNext(jsonObjectIterator* iter);
+
+/**
+ @param iter The iterator.
+ @return True if there is another node after the current node.
+ */
+int jsonObjectIteratorHasNext(const jsonObjectIterator* iter);
+
+
+#endif
+
+
Modified: branches/autotools/include/opensrf/osrf_message.h
===================================================================
--- branches/autotools/include/opensrf/osrf_message.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/opensrf/osrf_message.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,8 +1,7 @@
#include <opensrf/string_array.h>
#include <opensrf/utils.h>
#include <opensrf/log.h>
-#include <objson/object.h>
-#include <objson/json_parser.h>
+#include <opensrf/osrf_json.h>
/* libxml stuff for the config reader */
@@ -76,22 +75,44 @@
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 );
-void osrf_message_set_status_info( osrf_message*, char* status_name, char* status_text, int status_code );
-void osrf_message_set_result_content( osrf_message*, char* json_string );
+void osrf_message_set_status_info( osrf_message*,
+ const char* status_name, const char* status_text, int status_code );
+void osrf_message_set_result_content( osrf_message*, const char* json_string );
void osrfMessageFree( osrfMessage* );
void osrf_message_free( osrf_message* );
char* osrf_message_to_xml( osrf_message* );
-char* osrf_message_serialize(osrf_message*);
+char* osrf_message_serialize(const osrf_message*);
/* count is the max number of messages we'll put into msgs[] */
-int osrf_message_deserialize(char* json, osrf_message* msgs[], int count);
+int osrf_message_deserialize(const char* json, osrf_message* msgs[], int count);
@@ -101,10 +122,10 @@
*/
int osrf_message_from_xml( char* xml, osrf_message* msgs[] );
-void osrf_message_set_params( osrf_message* msg, jsonObject* o );
-void osrf_message_set_method( osrf_message* msg, char* method_name );
-void osrf_message_add_object_param( osrf_message* msg, jsonObject* o );
-void osrf_message_add_param( osrf_message*, char* param_string );
+void osrf_message_set_params( osrf_message* msg, const jsonObject* o );
+void osrf_message_set_method( osrf_message* msg, const char* method_name );
+void osrf_message_add_object_param( osrf_message* msg, const jsonObject* o );
+void osrf_message_add_param( osrf_message*, const char* param_string );
jsonObject* osrfMessageGetResult( osrfMessage* msg );
@@ -113,7 +134,7 @@
Returns the message as a jsonObject
@return The jsonObject which must be freed by the caller.
*/
-jsonObject* osrfMessageToJSON( osrfMessage* msg );
+jsonObject* osrfMessageToJSON( const osrfMessage* msg );
char* osrfMessageSerializeBatch( osrfMessage* msgs [], int count );
Modified: branches/autotools/include/opensrf/osrf_settings.h
===================================================================
--- branches/autotools/include/opensrf/osrf_settings.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/opensrf/osrf_settings.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -12,8 +12,7 @@
#include <opensrf/utils.h>
#include <opensrf/osrf_app_session.h>
-#include <objson/object.h>
-#include <objson/json_parser.h>
+#include <opensrf/osrf_json.h>
typedef struct {
char* hostname;
@@ -21,11 +20,11 @@
} osrf_host_config;
-osrf_host_config* osrf_settings_new_host_config(char* hostname);
+osrf_host_config* osrf_settings_new_host_config(const char* hostname);
void osrf_settings_free_host_config(osrf_host_config*);
-char* osrf_settings_host_value(char* path, ...);
-jsonObject* osrf_settings_host_value_object(char* format, ...);
-int osrf_settings_retrieve(char* hostname);
+char* osrf_settings_host_value(const char* path, ...);
+jsonObject* osrf_settings_host_value_object(const char* format, ...);
+int osrf_settings_retrieve(const char* hostname);
#endif
Modified: branches/autotools/include/opensrf/string_array.h
===================================================================
--- branches/autotools/include/opensrf/string_array.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/opensrf/string_array.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -2,17 +2,20 @@
#include <opensrf/utils.h>
#include <opensrf/log.h>
+#include <opensrf/osrf_list.h>
-#define STRING_ARRAY_MAX_SIZE 1024
+#define STRING_ARRAY_MAX_SIZE 4096
#ifndef STRING_ARRAY_H
#define STRING_ARRAY_H
+#define OSRF_STRING_ARRAY_FREE(arr)\
+ if(arr) {osrfListFree(arr->list); free(arr);}
+
+
struct string_array_struct {
- char** array;
- int size;
- int arr_size;
- int total_string_size;
+ osrfList* list;
+ int size;
};
typedef struct string_array_struct string_array;
typedef struct string_array_struct osrfStringArray;
Modified: branches/autotools/include/opensrf/utils.h
===================================================================
--- branches/autotools/include/opensrf/utils.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/opensrf/utils.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -41,6 +41,18 @@
memset( ptr, 0, size );\
} while(0)
+#ifndef NDEBUG
+// The original ... replace with noop once no more errors occur in NDEBUG mode
+#define osrf_clearbuf( s, n ) memset( s, 0, n )
+#else
+#define osrf_clearbuf( s, n ) \
+ do { \
+ char * clearbuf_temp_s = (s); \
+ size_t clearbuf_temp_n = (n); \
+ memset( clearbuf_temp_s, '!', clearbuf_temp_n ); \
+ clearbuf_temp_s[ clearbuf_temp_n - 1 ] = '\0'; \
+ } while( 0 )
+#endif
#define OSRF_BUFFER_ADD(gb, data) \
do {\
@@ -64,6 +76,10 @@
}\
}while(0)
+#define OSRF_BUFFER_RESET(gb) \
+ memset(gb->buf, 0, gb->size);\
+ gb->n_used = 0;
+
@@ -155,6 +171,7 @@
int daemonize();
void* safe_malloc(int size);
+void* safe_calloc(int size);
// ---------------------------------------------------------------------------------
// Generic growing buffer. Add data all you want
Modified: branches/autotools/include/opensrf/xml_utils.h
===================================================================
--- branches/autotools/include/opensrf/xml_utils.h 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/include/opensrf/xml_utils.h 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,7 +1,7 @@
#ifndef _XML_UTILS_H
#define _XML_UTILS_H
-#include <objson/object.h>
+#include <opensrf/osrf_json.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
Modified: branches/autotools/install.conf
===================================================================
--- branches/autotools/install.conf 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/install.conf 2007-11-05 13:40:16 UTC (rev 1121)
@@ -12,3 +12,4 @@
export APACHE2_HEADERS=/usr/include/apache2
export APR_HEADERS=/usr/include/apr-1.0/
export LIBXML2_HEADERS=/usr/include/libxml2/
+export OSRF_LEGACY_JSON=1
Modified: branches/autotools/src/Makefile
===================================================================
--- branches/autotools/src/Makefile 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/Makefile 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,18 +1,23 @@
# TOP level 'src' makefile for OpenSRF
-export TMPDIR = $(TMP)/opensrf
-export OPENSRF = opensrf
-export BINDIR = $(PREFIX)/bin
-export LIBDIR = $(PREFIX)/lib
-export PERLDIR = $(LIBDIR)/perl5
-export INCLUDEDIR = $(PREFIX)/include
+export TMPDIR = $(TMP)/opensrf
+export OPENSRF = opensrf
+export BINDIR = $(PREFIX)/bin
+export LIBDIR = $(PREFIX)/lib
+export PERLDIR = $(LIBDIR)/perl5
+export PYTHON25DIR = $(LIBDIR)/python25
+export JSDIR = $(LIBDIR)/javascript
+export INCLUDEDIR= $(PREFIX)/include
-export LDLIBS +=
-export LDFLAGS += -Wl,-rpath=$(LIBDIR) -L $(TMPDIR) -L .
-export CFLAGS += -pipe -g -Wall -O2 -fPIC -I ../../include/ -I$(LIBXML2_HEADERS) -I$(APACHE2_HEADERS) \
- -I$(LIBXML2_HEADERS)/libxml -I$(APR_HEADERS)
+export LDLIBS +=
+export LDFLAGS += -Wl,-rpath=$(LIBDIR) -L $(TMPDIR) -L .
+export CFLAGS += -D_LARGEFILE64_SOURCE -pipe -g -Wall -O2 -fPIC -I ../../include/ -I$(LIBXML2_HEADERS) -I$(APACHE2_HEADERS) -I$(APR_HEADERS)
+ifeq ($(OSRF_LEGACY_JSON), 1)
+export LDLIBS += -lobjson
+endif
+
all: prep \
opensrf \
router \
@@ -26,8 +31,9 @@
router-install \
srfsh-install \
jserver-install \
+ javascript-install \
perl-install \
- objson-install
+ python25-install
# --------------------------------------------------------------------------------
@@ -37,11 +43,7 @@
prep:
mkdir -p $(TMPDIR)
-objson/libobjson.so: prep
- @echo $@
- make -C objson
-
-opensrf: objson/libobjson.so
+opensrf: prep
make -C libopensrf
make -C c-apps
@@ -71,16 +73,14 @@
@echo $@
mkdir -p $(LIBDIR)
mkdir -p $(BINDIR)
+ mkdir -p $(JSDIR)
mkdir -p $(PERLDIR)
+ mkdir -p $(PYTHON25DIR)
mkdir -p $(INCLUDEDIR)
mkdir -p $(ETCDIR)
-objson-install: install-prep
- @echo $@
- make -C objson install
-
# installs libopensrf.so, opensrf-c, headers, example configs, and osrf_ctl.sh
-opensrf-install: objson-install
+opensrf-install: install-prep
@echo $@
cp $(TMPDIR)/libopensrf.so $(LIBDIR)/libopensrf.so
cp -r ../include/opensrf $(INCLUDEDIR)
@@ -90,6 +90,10 @@
cp ../examples/opensrf.xml.example $(ETCDIR)
cp ../examples/opensrf_core.xml.example $(ETCDIR)
cp ../examples/srfsh.xml.example $(ETCDIR)
+ if [ ! -z "$(OSRF_LEGACY_JSON)" ]; then\
+ cp -r ../include/objson $(INCLUDEDIR);\
+ cp $(TMPDIR)/libobjson.so $(LIBDIR);\
+ fi
gateway-install: install-prep opensrf-install
@echo $@
@@ -107,11 +111,19 @@
@echo $@
make -C jserver install
+javascript-install: install-prep
+ @echo $@
+ cp -r javascript/* $(JSDIR)/
+
perl-install: install-prep
@echo $@
cp -r perlmods/* $(PERLDIR)/
+python25-install: install-prep
+ @echo $@
+ cp -r python/* $(PYTHON25DIR)/
+
# --------------------------------------------------------------------------------
# CLEAN
# --------------------------------------------------------------------------------
@@ -120,7 +132,6 @@
make -C router clean
make -C gateway clean
make -C jserver clean
- make -C objson clean
make -C srfsh clean
make -C c-apps clean
/bin/rm -rf $(TMPDIR) *.o
Modified: branches/autotools/src/c-apps/Makefile
===================================================================
--- branches/autotools/src/c-apps/Makefile 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/c-apps/Makefile 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,5 +1,5 @@
-LDLIBS += -lobjson -lopensrf
-CFLAGS += -DOSRF_LOG_PARAMS
+LDLIBS += -lopensrf
+CFLAGS += -D_LARGEFILE64_SOURCE -DOSRF_LOG_PARAMS
all: osrf_math.so osrf_dbmath.so osrf_version.so
Modified: branches/autotools/src/c-apps/osrf_dbmath.c
===================================================================
--- branches/autotools/src/c-apps/osrf_dbmath.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/c-apps/osrf_dbmath.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,7 +1,7 @@
-#include "opensrf/osrf_app_session.h"
-#include "opensrf/osrf_application.h"
-#include "objson/object.h"
-#include "opensrf/log.h"
+#include <opensrf/osrf_app_session.h>
+#include <opensrf/osrf_application.h>
+#include <opensrf/osrf_json.h>
+#include <opensrf/log.h>
#define MODULENAME "opensrf.dbmath"
Modified: branches/autotools/src/c-apps/osrf_math.c
===================================================================
--- branches/autotools/src/c-apps/osrf_math.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/c-apps/osrf_math.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,7 +1,7 @@
-#include "opensrf/osrf_app_session.h"
-#include "opensrf/osrf_application.h"
-#include "objson/object.h"
-#include "opensrf/log.h"
+#include <opensrf/osrf_app_session.h>
+#include <opensrf/osrf_application.h>
+#include <opensrf/osrf_json.h>
+#include <opensrf/log.h>
#define MODULENAME "opensrf.math"
Modified: branches/autotools/src/c-apps/osrf_version.c
===================================================================
--- branches/autotools/src/c-apps/osrf_version.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/c-apps/osrf_version.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,6 +1,6 @@
#include "opensrf/osrf_app_session.h"
#include "opensrf/osrf_application.h"
-#include "objson/object.h"
+#include "opensrf/osrf_json.h"
#include "opensrf/utils.h"
#include "opensrf/log.h"
Modified: branches/autotools/src/gateway/Makefile
===================================================================
--- branches/autotools/src/gateway/Makefile 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/gateway/Makefile 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,6 +1,6 @@
#CFLAGS += -DASSUME_STATELESS -DOSRF_GATEWAY_NASTY_DEBUG
CFLAGS += -DASSUME_STATELESS
-LDLIBS += -lobjson -lopensrf
+LDLIBS += -lopensrf
all: osrf_json_gateway.so copy
Modified: branches/autotools/src/gateway/apachetools.c
===================================================================
--- branches/autotools/src/gateway/apachetools.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/gateway/apachetools.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -24,7 +24,7 @@
if(ap_should_client_block(r)) {
char body[1025];
- memset(body,0,1025);
+ memset(body,0,sizeof(body));
buffer = buffer_init(1025);
@@ -40,7 +40,7 @@
}
buffer_add( buffer, body );
- memset(body,0,1025);
+ memset(body,0,sizeof(body));
osrfLogDebug(OSRF_LOG_MARK,
"gateway read %d bytes: %d bytes of data so far", bread, buffer->n_used);
@@ -49,7 +49,7 @@
if(buffer->n_used > APACHE_TOOLS_MAX_POST_SIZE) {
osrfLogError(OSRF_LOG_MARK, "gateway received POST larger "
- "than %d bytes. dropping reqeust", APACHE_TOOLS_MAX_POST_SIZE);
+ "than %d bytes. dropping request", APACHE_TOOLS_MAX_POST_SIZE);
buffer_free(buffer);
return NULL;
}
Modified: branches/autotools/src/gateway/osrf_json_gateway.c
===================================================================
--- branches/autotools/src/gateway/osrf_json_gateway.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/gateway/osrf_json_gateway.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -2,17 +2,21 @@
#include "opensrf/osrf_app_session.h"
#include "opensrf/osrf_system.h"
#include "opensrf/osrfConfig.h"
-#include "objson/object.h"
-#include "objson/json2xml.h"
-#include "objson/xml2json.h"
+#include <opensrf/osrf_json.h>
+#include <opensrf/osrf_json_xml.h>
+#include <opensrf/osrf_legacy_json.h>
#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
#define GATEWAY_DEFAULT_CONFIG "/openils/conf/opensrf_core.xml"
@@ -22,13 +26,25 @@
char* configfile; /* our bootstrap config file */
} osrf_json_gateway_config;
+typedef struct {
+ int legacyJSON;
+} osrf_json_gateway_dir_config;
+
+
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) {
+ if (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);
@@ -37,10 +53,20 @@
return NULL;
}
+static const char* osrf_json_gateway_set_json_proto(cmd_parms *parms, void *config, const char *arg) {
+ osrf_json_gateway_dir_config* cfg = (osrf_json_gateway_dir_config*) config;
+ cfg->legacyJSON = (!strcasecmp((char*) arg, "false")) ? 0 : 1;
+ return NULL;
+}
+
/* tell apache about our commands */
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}
};
@@ -52,14 +78,20 @@
return (void*) cfg;
}
+static void* osrf_json_gateway_create_dir_config( apr_pool_t* p, char* dir) {
+ osrf_json_gateway_dir_config* cfg = (osrf_json_gateway_dir_config*)
+ apr_palloc(p, sizeof(osrf_json_gateway_dir_config));
+ cfg->legacyJSON = GATEWAY_USE_LEGACY_JSON;
+ return (void*) cfg;
+}
+
static void osrf_json_gateway_child_init(apr_pool_t *p, server_rec *s) {
char* cfg = osrf_json_gateway_config_file;
char buf[32];
- memset(buf, 0x0, 32);
int t = time(NULL);
- snprintf(buf, 32, "%d", t);
+ snprintf(buf, sizeof(buf), "%d", t);
if( ! osrfSystemBootstrapClientResc( cfg, CONFIG_CONTEXT, buf ) ) {
ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
@@ -84,6 +116,25 @@
/* make sure we're needed first thing*/
if (strcmp(r->handler, MODULE_NAME )) return DECLINED;
+
+ osrf_json_gateway_dir_config* dir_conf =
+ ap_get_module_config(r->per_dir_config, &osrf_json_gateway_module);
+
+
+ /* provide 2 different JSON parsers and serializers to support legacy JSON */
+ jsonObject* (*parseJSONFunc) (const char*) = legacy_jsonParseString;
+ char* (*jsonToStringFunc) (const jsonObject*) = legacy_jsonObjectToJSON;
+
+ if(dir_conf->legacyJSON) {
+ ap_log_rerror( APLOG_MARK, APLOG_INFO, 0, r, "Using legacy JSON");
+
+ } else {
+ ap_log_rerror( APLOG_MARK, APLOG_INFO, 0, r, "Not using legacy JSON");
+ parseJSONFunc = jsonParseString;
+ jsonToStringFunc = jsonObjectToJSON;
+ }
+
+
osrfLogDebug(OSRF_LOG_MARK, "osrf gateway: entered request handler");
/* verify we are connected */
@@ -96,41 +147,43 @@
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 */
- char* a_l = NULL; /* request api level */
- char* input_format = NULL; /* POST data format, defaults to 'format' */
- int isXML = 0;
- int api_level = 1;
+ char* a_l = NULL; /* request api level */
+ char* input_format = NULL; /* POST data format, defaults to 'format' */
+ int isXML = 0;
+ int api_level = 1;
r->allowed |= (AP_METHOD_BIT << M_GET);
r->allowed |= (AP_METHOD_BIT << M_POST);
osrfLogDebug(OSRF_LOG_MARK, "osrf gateway: parsing URL params");
string_array* mparams = NULL;
- string_array* params = apacheParseParms(r); /* free me */
- service = apacheGetFirstParamValue( params, "service" );
- method = apacheGetFirstParamValue( params, "method" );
- format = apacheGetFirstParamValue( params, "format" );
- input_format = apacheGetFirstParamValue( params, "input_format" );
+ string_array* params = apacheParseParms(r); /* free me */
+ param_locale = apacheGetFirstParamValue( params, "locale" );
+ service = apacheGetFirstParamValue( params, "service" );
+ method = apacheGetFirstParamValue( params, "method" );
+ format = apacheGetFirstParamValue( params, "format" );
+ input_format = apacheGetFirstParamValue( params, "input_format" );
a_l = apacheGetFirstParamValue( params, "api_level" );
- mparams = apacheGetParamValues( params, "param" ); /* free me */
+ mparams = apacheGetParamValues( params, "param" ); /* free me */
- if(format == NULL)
- format = "json";
- if(input_format == NULL)
- input_format = format;
+ if(format == NULL)
+ format = "json";
+ if(input_format == NULL)
+ input_format = format;
- /* set the user defined timeout value */
- int timeout = 60;
- char* tout = apacheGetFirstParamValue( params, "timeout" ); /* request timeout in seconds */
- if( tout ) {
- timeout = atoi(tout);
- osrfLogDebug(OSRF_LOG_MARK, "Client supplied timeout of %d", timeout);
- }
+ /* set the user defined timeout value */
+ int timeout = 60;
+ char* tout = apacheGetFirstParamValue( params, "timeout" ); /* request timeout in seconds */
+ if( tout ) {
+ timeout = atoi(tout);
+ osrfLogDebug(OSRF_LOG_MARK, "Client supplied timeout of %d", timeout);
+ }
-
if (a_l)
api_level = atoi(a_l);
@@ -143,6 +196,38 @@
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 && 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)) {
@@ -164,33 +249,41 @@
*/
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;
- if(!strcasecmp(input_format, "json")) {
- req_id = osrf_app_session_make_req( session, NULL, method, api_level, mparams );
+ if(!strcasecmp(input_format, "json")) {
+ jsonObject * arr = jsonNewObject(NULL);
- } else {
+ char* str;
+ int i = 0;
- /**
- * If we receive XML method params, convert each param to a JSON object
- * and pass the array of JSON object params to the method */
- if(!strcasecmp(input_format, "xml")) {
- jsonObject* jsonParams = jsonNewObject(NULL);
+ while( (str = osrfStringArrayGetString(mparams, i++)) )
+ jsonObjectPush(arr, parseJSONFunc(str));
- char* str;
- int i = 0;
- while( (str = osrfStringArrayGetString(mparams, i++)) ) {
- jsonObjectPush(jsonParams, jsonXMLToJSONObject(str));
- }
+ req_id = osrf_app_session_make_req( session, arr, method, api_level, NULL );
+ } else {
- req_id = osrf_app_session_make_req( session, jsonParams, method, api_level, NULL );
- jsonObjectFree(jsonParams);
- }
- }
+ /**
+ * If we receive XML method params, convert each param to a JSON object
+ * and pass the array of JSON object params to the method */
+ if(!strcasecmp(input_format, "xml")) {
+ jsonObject* jsonParams = jsonNewObject(NULL);
+ char* str;
+ int i = 0;
+ while( (str = osrfStringArrayGetString(mparams, i++)) ) {
+ jsonObjectPush(jsonParams, jsonXMLToJSONObject(str));
+ }
+ req_id = osrf_app_session_make_req( session, jsonParams, method, api_level, NULL );
+ jsonObjectFree(jsonParams);
+ }
+ }
+
+
if( req_id == -1 ) {
osrfLogError(OSRF_LOG_MARK, "I am unable to communcate with opensrf..going away...");
/* we don't want to spawn an intense re-forking storm
@@ -209,7 +302,7 @@
char* str; int i = 0;
while( (str = osrfStringArrayGetString(mparams, i++)) ) {
if( i == 1 ) {
- OSRF_BUFFER_ADD(act, " ");
+ OSRF_BUFFER_ADD(act, " ");
OSRF_BUFFER_ADD(act, str);
} else {
OSRF_BUFFER_ADD(act, ", ");
@@ -247,7 +340,7 @@
if (isXML) {
output = jsonObjectToXML( res );
} else {
- output = jsonObjectToJSON( res );
+ output = jsonToStringFunc( res );
if( morethan1 ) ap_rputs(",", r); /* comma between JSON array items */
}
ap_rputs(output, r);
@@ -283,18 +376,16 @@
"OpenSRF JSON Request returned error: %s -> %s", statusname, statustext );
int l = strlen(statusname) + strlen(statustext) + 32;
char buf[l];
- bzero(buf,l);
if (isXML)
- snprintf( buf, l, "<debug>\"%s : %s\"</debug>", statusname, statustext );
+ snprintf( buf, sizeof(buf), "<debug>\"%s : %s\"</debug>", statusname, statustext );
else {
char bb[l];
- bzero(bb, l);
- snprintf(bb, l, "%s : %s", statusname, statustext);
+ snprintf(bb, sizeof(bb), "%s : %s", statusname, statustext);
jsonObject* tmp = jsonNewObject(bb);
- char* j = jsonObjectToJSON(tmp);
- snprintf( buf, l, ",\"debug\": %s", j);
+ char* j = jsonToStringFunc(tmp);
+ snprintf( buf, sizeof(buf), ",\"debug\": %s", j);
free(j);
jsonObjectFree(tmp);
}
@@ -307,12 +398,11 @@
/* insert the status code */
char buf[32];
- bzero(buf,32);
if (isXML)
- snprintf(buf, 32, "<status>%d</status>", statuscode );
+ snprintf(buf, sizeof(buf), "<status>%d</status>", statuscode );
else
- snprintf(buf, 32, ",\"status\":%d", statuscode );
+ snprintf(buf, sizeof(buf), ",\"status\":%d", statuscode );
ap_rputs( buf, r );
@@ -329,7 +419,7 @@
string_array_destroy(mparams);
osrfLogDebug(OSRF_LOG_MARK, "Gateway served %d requests", ++numserved);
- osrfLogClearXid();
+ osrfLogClearXid();
return ret;
}
@@ -344,8 +434,8 @@
module AP_MODULE_DECLARE_DATA osrf_json_gateway_module = {
STANDARD20_MODULE_STUFF,
+ osrf_json_gateway_create_dir_config,
NULL,
- NULL,
osrf_json_gateway_create_config,
NULL,
osrf_json_gateway_cmds,
Modified: branches/autotools/src/java/Makefile
===================================================================
--- branches/autotools/src/java/Makefile 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/java/Makefile 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,18 +1,43 @@
-#JAVA_LIBS = .:lib:ext/json-jdk1.5-2007-05-01.jar:ext/wstx-asl-3.2.1.jar:ext/stax-api-1.0.1.jar:ext/xercesImpl-1.4.4-2.jar
-JAVA_LIBDIR = .lib
+# dependencies
+STAX=stax-api-1.0.1.jar
+WSTX=wstx-lgpl-3.2.1.jar
+MEMCACHE=java_memcached-release_1.5.1.jar
+JSON=json.zip
+
+STAX_URL=http://woodstox.codehaus.org/$(STAX)
+WSTX_URL=http://woodstox.codehaus.org/3.2.1/$(WSTX)
+MEMCACHE_URL=http://img.whalin.com/memcached/jdk5/standard/$(MEMCACHE)
+JSON_URL=http://www.json.org/java/$(JSON)
+
+
JAVAC=javac -J-Xmx256m
JAVA=java -Xmx256m
-JAVA_LIBS = .:$(JAVA_LIBDIR):ext/json-jdk1.5-2007-05-01.jar:ext/wstx-lgpl-3.2.1.jar:ext/stax-api-1.0.1.jar:ext/java_memcached-release_1.5.1.jar
+JAVA_LIBDIR = .lib
+JAVA_LIBS = .:$(JAVA_LIBDIR):ext/$(WSTX):ext/$(STAX):ext/$(MEMCACHE)
JAVA_SRC = \
org/opensrf/net/xmpp/*.java \
org/opensrf/util/*.java \
org/opensrf/*.java \
org/opensrf/test/*.java
-all:
+
+#------------------------------------------------------------------
+
+all: jar
+
+
+dirs:
mkdir -p $(JAVA_LIBDIR)
+
+opensrf: deps
$(JAVAC) -d $(JAVA_LIBDIR) -cp $(JAVA_LIBS) $(JAVA_SRC) 2>&1
+jar: opensrf
+ rm -f opensrf.jar
+ echo "creating opensrf.jar"
+ jar cf opensrf.jar -C .lib org
+ rm -r $(JAVA_LIBDIR)
+
# only prints the first 30 lines of errors
slim:
mkdir -p $(JAVA_LIBDIR)
@@ -25,14 +50,15 @@
@echo -e "\nTruncating at 30 lines"
run:
- @$(JAVA) -cp $(JAVA_LIBS) $(JAVA_EXE) $(JAVA_ARGS)
+ $(JAVA) -cp $(JAVA_LIBS):opensrf.jar $(JAVA_EXE) $(JAVA_ARGS)
deps:
mkdir -p ext
- wget 'http://woodstox.codehaus.org/stax-api-1.0.1.jar' -O ext/stax-api-1.0.1.jar
- wget 'http://woodstox.codehaus.org/3.2.1/wstx-lgpl-3.2.1.jar' -O ext/wstx-lgpl-3.2.1.jar
- wget 'http://img.whalin.com/memcached/jdk5/standard/java_memcached-release_1.5.1.jar' -O ext/java_memcached-release_1.5.1.jar
- mkdir -p .tmp && cd .tmp && wget 'http://www.json.org/java/json.zip' && unzip json.zip
+ mkdir -p $(JAVA_LIBDIR)
+ if [ ! -f ext/$(STAX) ]; then wget '$(STAX_URL)' -O ext/$(STAX); fi
+ if [ ! -f ext/wstx-lgpl-3.2.1.jar ]; then wget '$(WSTX_URL)' -O ext/$(WSTX); fi
+ if [ ! -f ext/java_memcached-release_1.5.1.jar ]; then wget '$(MEMCACHE_URL)' -O ext/$(MEMCACHE); fi
+ if [ ! -f .tmp/$(JSON) ]; then mkdir -p .tmp && cd .tmp && wget '$(JSON_URL)' && unzip $(JSON); fi
$(JAVAC) -d $(JAVA_LIBDIR) .tmp/org/json/*.java
docs:
@@ -40,8 +66,10 @@
javadoc -classpath $(JAVA_LIBS) -d doc @files;
rm files;
-clean:
- rm -r $(JAVA_LIBDIR)
-
+clean:
+ rm -rf $(JAVA_LIBDIR) opensrf.jar
+dep_clean:
+ rm -rf ext .tmp
+
Modified: branches/autotools/src/java/org/opensrf/ClientSession.java
===================================================================
--- branches/autotools/src/java/org/opensrf/ClientSession.java 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/java/org/opensrf/ClientSession.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -51,7 +51,7 @@
/** create a random thread */
long time = new Date().getTime();
Random rand = new Random(time);
- setThread(rand.nextInt()+""+rand.nextInt()+""+time);
+ setThread(rand.nextInt()+""+rand.nextInt()+""+time+Thread.currentThread().getId());
nextId = 0;
requests = new HashMap<Integer, Request>();
@@ -115,6 +115,7 @@
Request req = findRequest(msg.getId());
if(req == null) {
/** LOG that we've received a result to a non-existant request */
+ System.err.println(msg.getId() +" has no corresponding request");
return;
}
OSRFObject payload = (OSRFObject) msg.get("payload");
@@ -145,5 +146,19 @@
if(req == null) return;
req.setComplete();
}
+
+ public static Object atomicRequest(String service, String method, Object[] params) throws MethodException {
+ try {
+ ClientSession session = new ClientSession(service);
+ Request osrfRequest = session.request(method, params);
+ Result result = osrfRequest.recv(600000);
+ if(result.getStatusCode() != 200)
+ throw new MethodException(
+ "Request "+service+":"+method+":"+" failed with status code " + result.getStatusCode());
+ return result.getContent();
+ } catch(Exception e) {
+ throw new MethodException(e);
+ }
+ }
}
Modified: branches/autotools/src/java/org/opensrf/MethodException.java
===================================================================
--- branches/autotools/src/java/org/opensrf/MethodException.java 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/java/org/opensrf/MethodException.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -7,5 +7,8 @@
public MethodException(String info) {
super(info);
}
+ public MethodException(Throwable cause) {
+ super(cause);
+ }
}
Modified: branches/autotools/src/java/org/opensrf/Request.java
===================================================================
--- branches/autotools/src/java/org/opensrf/Request.java 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/java/org/opensrf/Request.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -73,11 +73,16 @@
Result result = null;
+ if((result = resultQueue.poll()) != null)
+ return result;
+
if(millis < 0 && !complete) {
/** wait potentially forever for a result to arrive */
- session.waitForMessage(millis);
- if((result = resultQueue.poll()) != null)
- return result;
+ while(!complete) {
+ session.waitForMessage(millis);
+ if((result = resultQueue.poll()) != null)
+ return result;
+ }
} else {
Modified: branches/autotools/src/java/org/opensrf/Session.java
===================================================================
--- branches/autotools/src/java/org/opensrf/Session.java 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/java/org/opensrf/Session.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -45,10 +45,9 @@
xmsg.setTo(remoteNode);
xmsg.setThread(thread);
xmsg.setBody(new JSONWriter(Arrays.asList(new Message[] {omsg})).write());
- XMPPSession ses = XMPPSession.getGlobalSession();
try {
- XMPPSession.getGlobalSession().send(xmsg);
+ XMPPSession.getThreadSession().send(xmsg);
} catch(XMPPException e) {
connectState = ConnectState.DISCONNECTED;
throw new SessionException("Error sending message to " + remoteNode, e);
@@ -63,7 +62,7 @@
public static void waitForMessage(long millis) throws SessionException, MethodException {
try {
Stack.processXMPPMessage(
- XMPPSession.getGlobalSession().recv(millis));
+ XMPPSession.getThreadSession().recv(millis));
} catch(XMPPException e) {
throw new SessionException("Error waiting for message", e);
}
Modified: branches/autotools/src/java/org/opensrf/Sys.java
===================================================================
--- branches/autotools/src/java/org/opensrf/Sys.java 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/java/org/opensrf/Sys.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -2,6 +2,9 @@
import org.opensrf.util.*;
import org.opensrf.net.xmpp.*;
+import java.util.Random;
+import java.util.Date;
+import java.net.InetAddress;
public class Sys {
@@ -16,6 +19,14 @@
public static void bootstrapClient(String configFile, String configContext)
throws ConfigException, SessionException {
+ if(Logger.instance() == null) /* provide a sane default logger */
+ Logger.init(Logger.WARN, new Logger());
+
+ /** see if the current thread already has a connection */
+ XMPPSession existing = XMPPSession.getThreadSession();
+ if(existing != null && existing.connected())
+ return;
+
/** create the config parser */
Config config = new Config(configContext);
config.parse(configFile);
@@ -27,11 +38,24 @@
String host = (String) config.getFirst("/domains/domain");
int port = config.getInt("/port");
+
+ /** Create a random login resource string */
+ String res = "java_";
try {
+ res += InetAddress.getLocalHost().getHostAddress();
+ } catch(java.net.UnknownHostException e) {}
+ res += "_"+Math.abs(new Random(new Date().getTime()).nextInt())
+ + "_t"+ Thread.currentThread().getId();
+
+
+ try {
+
/** Connect to the Jabber network */
+ Logger.info("attempting to create XMPP session "+username+"@"+host+"/"+res);
XMPPSession xses = new XMPPSession(host, port);
- xses.connect(username, passwd, "test-java"); /* XXX */
- XMPPSession.setGlobalSession(xses);
+ xses.connect(username, passwd, res);
+ XMPPSession.setThreadSession(xses);
+
} catch(XMPPException e) {
throw new SessionException("Unable to bootstrap client", e);
}
@@ -41,7 +65,7 @@
* Shuts down the connection to the opensrf network
*/
public static void shutdown() {
- XMPPSession.getGlobalSession().disconnect();
+ XMPPSession.getThreadSession().disconnect();
}
}
Modified: branches/autotools/src/java/org/opensrf/net/xmpp/XMPPReader.java
===================================================================
--- branches/autotools/src/java/org/opensrf/net/xmpp/XMPPReader.java 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/java/org/opensrf/net/xmpp/XMPPReader.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -8,6 +8,7 @@
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.Date;
+import com.ctc.wstx.stax.WstxInputFactory;
/**
* Slim XMPP Stream reader. This reader only understands enough XMPP
@@ -118,7 +119,7 @@
* Each reader should have exactly one dependent session thread.
*/
private synchronized void notifyCoreEvent() {
- notify();
+ notifyAll();
}
@@ -133,11 +134,13 @@
public synchronized long waitCoreEvent(long timeout) {
if(msgQueue.peek() != null || timeout == 0) return 0;
+ long start = new Date().getTime();
- long start = new Date().getTime();
try{
- if(timeout < 0) wait();
- else wait(timeout);
+ if(timeout < 0)
+ wait();
+ else
+ wait(timeout);
} catch(InterruptedException ie) {}
return new Date().getTime() - start;
@@ -158,7 +161,8 @@
try {
- XMLInputFactory factory = XMLInputFactory.newInstance();
+ //XMLInputFactory factory = XMLInputFactory.newInstance();
+ XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory();
/** disable as many unused features as possible to speed up the parsing */
factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE);
Modified: branches/autotools/src/java/org/opensrf/net/xmpp/XMPPSession.java
===================================================================
--- branches/autotools/src/java/org/opensrf/net/xmpp/XMPPSession.java 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/java/org/opensrf/net/xmpp/XMPPSession.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -2,6 +2,9 @@
import java.io.*;
import java.net.Socket;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
/**
@@ -21,6 +24,8 @@
public static final String JABBER_DISCONNECT = "</stream:stream>";
+ private static Map threadConnections = new ConcurrentHashMap();
+
/** jabber domain */
private String host;
/** jabber port */
@@ -59,24 +64,65 @@
/**
* Returns the global, process-wide session
*/
+ /*
public static XMPPSession getGlobalSession() {
return globalSession;
}
+ */
+ public static XMPPSession getThreadSession() {
+ return (XMPPSession) threadConnections.get(new Long(Thread.currentThread().getId()));
+ }
+
/**
+ * Sets the given session as the global session for the current thread
+ * @param ses The session
+ */
+ public static void setThreadSession(XMPPSession ses) {
+ /* every time we create a new connection, clean up any dead threads.
+ * this is cheaper than cleaning up the dead threads at every access. */
+ cleanupThreadSessions();
+ threadConnections.put(new Long(Thread.currentThread().getId()), ses);
+ }
+
+ /**
+ * Analyzes the threadSession data to see if there are any sessions
+ * whose controlling thread has gone away.
+ */
+ private static void cleanupThreadSessions() {
+ Thread threads[] = new Thread[Thread.activeCount()];
+ Thread.enumerate(threads);
+ for(Iterator i = threadConnections.keySet().iterator(); i.hasNext(); ) {
+ boolean found = false;
+ Long id = (Long) i.next();
+ for(Thread t : threads) {
+ if(t.getId() == id.longValue()) {
+ found = true;
+ break;
+ }
+ }
+ if(!found)
+ threadConnections.remove(id);
+ }
+ }
+
+ /**
* Sets the global, process-wide section
*/
+ /*
public static void setGlobalSession(XMPPSession ses) {
globalSession = ses;
}
+ */
/** true if this session is connected to the server */
public boolean connected() {
return (
- reader != null &&
- reader.getXMPPStreamState() ==
- XMPPReader.XMPPStreamState.CONNECTED);
+ reader != null &&
+ reader.getXMPPStreamState() == XMPPReader.XMPPStreamState.CONNECTED &&
+ !socket.isClosed()
+ );
}
@@ -113,29 +159,33 @@
thread.setDaemon(true);
thread.start();
- /* send the initial jabber message */
- sendConnect();
- reader.waitCoreEvent(10000);
+ synchronized(reader) {
+ /* send the initial jabber message */
+ sendConnect();
+ reader.waitCoreEvent(10000);
+ }
if( reader.getXMPPStreamState() != XMPPReader.XMPPStreamState.CONNECT_RECV )
throw new XMPPException("unable to connect to jabber server");
- /* send the basic auth message */
- sendBasicAuth(); /* XXX add support for other auth mechanisms */
- reader.waitCoreEvent(10000);
- if(!connected())
+ synchronized(reader) {
+ /* send the basic auth message */
+ sendBasicAuth();
+ reader.waitCoreEvent(10000);
+ }
+ if(!connected())
throw new XMPPException("Authentication failed");
}
/** Sends the initial jabber message */
private void sendConnect() {
+ reader.setXMPPStreamState(XMPPReader.XMPPStreamState.CONNECT_SENT);
writer.printf(JABBER_CONNECT, host);
- reader.setXMPPStreamState(XMPPReader.XMPPStreamState.CONNECT_SENT);
}
/** Send the basic auth message */
private void sendBasicAuth() {
+ reader.setXMPPStreamState(XMPPReader.XMPPStreamState.AUTH_SENT);
writer.printf(JABBER_BASIC_AUTH, username, password, resource);
- reader.setXMPPStreamState(XMPPReader.XMPPStreamState.AUTH_SENT);
}
@@ -186,14 +236,17 @@
} else {
while(timeout >= 0) { /* wait at most 'timeout' milleseconds for a message to arrive */
+ msg = reader.popMessageQueue();
+ if( msg != null ) return msg;
timeout -= reader.waitCoreEvent(timeout);
msg = reader.popMessageQueue();
if( msg != null ) return msg;
checkConnected();
+ if(timeout == 0) break;
}
}
- return null;
+ return reader.popMessageQueue();
}
Modified: branches/autotools/src/java/org/opensrf/test/TestClient.java
===================================================================
--- branches/autotools/src/java/org/opensrf/test/TestClient.java 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/java/org/opensrf/test/TestClient.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -7,48 +7,72 @@
import java.util.ArrayList;
import java.io.PrintStream;
-
public class TestClient {
public static void main(String args[]) throws Exception {
+ /** which opensrf service are we sending our request to */
+ String service;
+ /** which opensrf method we're calling */
+ String method;
+ /** method params, captures from command-line args */
+ List<Object> params;
+ /** knows how to read JSON */
+ JSONReader reader;
+ /** opensrf request */
+ Request request;
+ /** request result */
+ Result result;
+ /** start time for the request */
+ long start;
+ /** for brevity */
PrintStream out = System.out;
+
if(args.length < 3) {
out.println( "usage: org.opensrf.test.TestClient "+
"<osrfConfigFile> <service> <method> [<JSONparam1>, <JSONparam2>]");
return;
}
+ /** connect to the opensrf network, default config context
+ * for opensrf_core.xml is /config/opensrf */
Sys.bootstrapClient(args[0], "/config/opensrf");
- String service = args[1];
- String method = args[2];
- /** build the client session and send the request */
- ClientSession session = new ClientSession(service);
- List<Object> params = new ArrayList<Object>();
- JSONReader reader;
-
- for(int i = 3; i < args.length; i++) /* add the params */
+ /* grab the server, method, and any params from the command line */
+ service = args[1];
+ method = args[2];
+ params = new ArrayList<Object>();
+ for(int i = 3; i < args.length; i++)
params.add(new JSONReader(args[i]).read());
- Result result;
+ /** build the client session */
+ ClientSession session = new ClientSession(service);
- long start = new Date().getTime();
- Request request = session.request(method, params);
+ /** kick off the timer */
+ start = new Date().getTime();
+ /** Create the request object from the session, method and params */
+ request = session.request(method, params);
+
while( (result = request.recv(60000)) != null ) {
/** loop over the results and print the JSON version of the content */
- if(result.getStatusCode() != 200) { /* make sure the request succeeded */
+ if(result.getStatusCode() != 200) {
+ /** make sure the request succeeded */
out.println("status = " + result.getStatus());
out.println("status code = " + result.getStatusCode());
continue;
}
- out.println("result JSON: " + new JSONWriter(result.getContent()).write());
+ /** JSON-ify the resulting object and print it */
+ out.println("\nresult JSON: " + new JSONWriter(result.getContent()).write());
}
+
+ /** How long did the request take? */
out.println("Request round trip took: " + (new Date().getTime() - start) + " ms.");
+
+ Sys.shutdown();
}
}
Copied: branches/autotools/src/java/org/opensrf/test/TestLog.java (from rev 1120, trunk/src/java/org/opensrf/test/TestLog.java)
===================================================================
--- branches/autotools/src/java/org/opensrf/test/TestLog.java (rev 0)
+++ branches/autotools/src/java/org/opensrf/test/TestLog.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,15 @@
+package org.opensrf.test;
+import org.opensrf.util.Logger;
+import org.opensrf.util.FileLogger;
+
+
+/** Simple test class for tesing the logging functionality */
+public class TestLog {
+ public static void main(String args[]) {
+ Logger.init(Logger.DEBUG, new FileLogger("test.log"));
+ Logger.error("Hello, world");
+ Logger.warn("Hello, world");
+ Logger.info("Hello, world");
+ Logger.debug("Hello, world");
+ }
+}
Copied: branches/autotools/src/java/org/opensrf/test/TestThread.java (from rev 1120, trunk/src/java/org/opensrf/test/TestThread.java)
===================================================================
--- branches/autotools/src/java/org/opensrf/test/TestThread.java (rev 0)
+++ branches/autotools/src/java/org/opensrf/test/TestThread.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,68 @@
+package org.opensrf.test;
+import org.opensrf.*;
+import org.opensrf.util.*;
+import java.util.Map;
+import java.util.Date;
+import java.util.List;
+import java.util.ArrayList;
+import java.io.PrintStream;
+
+/**
+ * Connects to the opensrf network once per thread and runs
+ * and runs a series of request acccross all launched threads.
+ * The purpose is to verify that the java threaded client api
+ * is functioning as expected
+ */
+public class TestThread implements Runnable {
+
+ String args[];
+
+ public TestThread(String args[]) {
+ this.args = args;
+ }
+
+ public void run() {
+
+ try {
+
+ Sys.bootstrapClient(args[0], "/config/opensrf");
+ ClientSession session = new ClientSession(args[3]);
+
+ List params = new ArrayList<Object>();
+ for(int i = 5; i < args.length; i++)
+ params.add(new JSONReader(args[3]).read());
+
+ for(int i = 0; i < Integer.parseInt(args[2]); i++) {
+ System.out.println("thread " + Thread.currentThread().getId()+" sending request " + i);
+ Request request = session.request(args[4], params);
+ Result result = request.recv(3000);
+ if(result != null) {
+ System.out.println("thread " + Thread.currentThread().getId()+
+ " got result JSON: " + new JSONWriter(result.getContent()).write());
+ } else {
+ System.out.println("* thread " + Thread.currentThread().getId()+ " got NO result");
+ }
+ }
+
+ Sys.shutdown();
+ } catch(Exception e) {
+ System.err.println(e);
+ }
+ }
+
+ public static void main(String args[]) throws Exception {
+
+ if(args.length < 5) {
+ System.out.println( "usage: org.opensrf.test.TestClient "+
+ "<osrfConfigFile> <numthreads> <numiter> <service> <method> [<JSONparam1>, <JSONparam2>]");
+ return;
+ }
+
+ int numThreads = Integer.parseInt(args[1]);
+ for(int i = 0; i < numThreads; i++)
+ new Thread(new TestThread(args)).start();
+ }
+}
+
+
+
Copied: branches/autotools/src/java/org/opensrf/util/FileLogger.java (from rev 1120, trunk/src/java/org/opensrf/util/FileLogger.java)
===================================================================
--- branches/autotools/src/java/org/opensrf/util/FileLogger.java (rev 0)
+++ branches/autotools/src/java/org/opensrf/util/FileLogger.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,44 @@
+package org.opensrf.util;
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+
+
+public class FileLogger extends Logger {
+
+ /** File to log to */
+ private String filename;
+
+ /**
+ * FileLogger constructor
+ * @param filename The path to the log file
+ */
+ public FileLogger(String filename) {
+ this.filename = filename;
+ }
+
+ /**
+ * Logs the mesage to a file.
+ * @param level The log level
+ * @param msg The mesage to log
+ */
+ protected synchronized void log(short level, String msg) {
+ if(level > logLevel) return;
+
+ BufferedWriter out = null;
+ try {
+ out = new BufferedWriter(new FileWriter(this.filename, true));
+ out.write(formatMessage(level, msg) + "\n");
+
+ } catch(Exception e) {
+ /** If we are unable to write our log message, go ahead and
+ * fall back to the default (stdout) logger */
+ Logger.init(logLevel, new Logger());
+ Logger.logByLevel(ERROR, "Unable to write to log file " + this.filename);
+ Logger.logByLevel(level, msg);
+ }
+
+ try {
+ out.close();
+ } catch(Exception e) {}
+ }
+}
Copied: branches/autotools/src/java/org/opensrf/util/Logger.java (from rev 1120, trunk/src/java/org/opensrf/util/Logger.java)
===================================================================
--- branches/autotools/src/java/org/opensrf/util/Logger.java (rev 0)
+++ branches/autotools/src/java/org/opensrf/util/Logger.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,130 @@
+package org.opensrf.util;
+import java.text.SimpleDateFormat;
+import java.text.FieldPosition;
+import java.util.Date;
+
+/**
+ * Basic OpenSRF logging API. This default implementation
+ * logs to stderr.
+ */
+public class Logger {
+
+ /** Log levels */
+ public static final short ERROR = 1;
+ public static final short WARN = 2;
+ public static final short INFO = 3;
+ public static final short DEBUG = 4;
+
+ /** The global log instance */
+ private static Logger instance;
+ /** The global log level */
+ protected static short logLevel;
+
+ public Logger() {}
+
+ /** Sets the global Logger instance
+ * @param level The global log level.
+ * @param l The Logger instance to use
+ */
+ public static void init(short level, Logger l) {
+ instance = l;
+ logLevel = level;
+ }
+
+ /**
+ * @return The global Logger instance
+ */
+ public static Logger instance() {
+ return instance;
+ }
+
+ /**
+ * Logs an error message
+ * @param msg The message to log
+ */
+ public static void error(String msg) {
+ instance.log(ERROR, msg);
+ }
+
+ /**
+ * Logs an warning message
+ * @param msg The message to log
+ */
+ public static void warn(String msg) {
+ instance.log(WARN, msg);
+ }
+
+ /**
+ * Logs an info message
+ * @param msg The message to log
+ */
+ public static void info(String msg) {
+ instance.log(INFO, msg);
+ }
+
+ /**
+ * Logs an debug message
+ * @param msg The message to log
+ */
+ public static void debug(String msg) {
+ instance.log(DEBUG, msg);
+ }
+
+ /**
+ * Appends the text representation of the log level
+ * @param sb The stringbuffer to append to
+ * @param level The log level
+ */
+ protected static void appendLevelString(StringBuffer sb, short level) {
+ switch(level) {
+ case DEBUG:
+ sb.append("DEBG"); break;
+ case INFO:
+ sb.append("INFO"); break;
+ case WARN:
+ sb.append("WARN"); break;
+ case ERROR:
+ sb.append("ERR "); break;
+ }
+ }
+
+ /**
+ * Formats a message for logging. Appends the current date+time
+ * and the log level string.
+ * @param level The log level
+ * @param msg The message to log
+ */
+ protected static String formatMessage(short level, String msg) {
+
+ StringBuffer sb = new StringBuffer();
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(
+ new Date(), sb, new FieldPosition(0));
+
+ sb.append(" [");
+ appendLevelString(sb, level);
+ sb.append("] ");
+ sb.append(msg);
+ return sb.toString();
+ }
+
+ /**
+ * Logs a message by passing the log level explicitly
+ * @param level The log level
+ * @param msg The message to log
+ */
+ public static void logByLevel(short level, String msg) {
+ instance.log(level, msg);
+ }
+
+ /**
+ * Performs the actual logging. Subclasses should override
+ * this method.
+ * @param level The log level
+ * @param msg The message to log
+ */
+ protected synchronized void log(short level, String msg) {
+ if(level > logLevel) return;
+ System.err.println(formatMessage(level, msg));
+ }
+}
+
Modified: branches/autotools/src/java/org/opensrf/util/OSRFObject.java
===================================================================
--- branches/autotools/src/java/org/opensrf/util/OSRFObject.java 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/java/org/opensrf/util/OSRFObject.java 2007-11-05 13:40:16 UTC (rev 1121)
@@ -16,6 +16,7 @@
public OSRFObject() {
}
+
/**
* Creates a new object with the provided registry
*/
@@ -24,7 +25,16 @@
registry = reg;
}
+
/**
+ * Creates a new OpenSRF object based on the net class string
+ * */
+ public OSRFObject(String netClass) {
+ this(OSRFRegistry.getRegistry(netClass));
+ }
+
+
+ /**
* @return This object's registry
*/
public OSRFRegistry getRegistry() {
Deleted: branches/autotools/src/javascript/JSON.js
===================================================================
--- branches/autotools/src/javascript/JSON.js 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/javascript/JSON.js 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,135 +0,0 @@
-// in case we run on an implimentation that doesn't have "undefined";
-var undefined;
-
-function Cast (obj, class_constructor) {
- try {
- if (eval(class_constructor + '["_isfieldmapper"]')) {
- obj = eval("new " + class_constructor + "(obj)");
- }
- } catch( E ) {
- alert( E + "\n");
- } finally {
- return obj;
- }
-}
-
-function JSON2js (json) {
-
- json = String(json).replace( /\/\*--\s*S\w*?\s*?\s+\w+\s*--\*\//g, 'Cast(');
- json = String(json).replace( /\/\*--\s*E\w*?\s*?\s+(\w+)\s*--\*\//g, ', "$1")');
-
- var obj;
- if (json != '') {
- try {
- eval( 'obj = ' + json );
- } catch(E) {
- debug("Error building JSON object with string " + E + "\nString:\n" + json );
- return null;
- }
- }
- return obj;
-}
-
-
-function object2Array(obj) {
- if( obj == null ) return null;
-
- var arr = new Array();
- for( var i = 0; i < obj.length; i++ ) {
- arr[i] = obj[i];
- }
- return arr;
-}
-
-
-function js2JSON(arg) {
- return _js2JSON(arg);
-}
-
-function _js2JSON(arg) {
- var i, o, u, v;
-
- switch (typeof arg) {
- case 'object':
-
- if(arg) {
-
- if (arg._isfieldmapper) { /* magi-c-ast for fieldmapper objects */
-
- if( arg.a.constructor != Array ) {
- var arr = new Array();
- for( var i = 0; i < arg.a.length; i++ ) {
- if( arg.a[i] == null ) {
- arr[i] = null; continue;
- }
-
- if( typeof arg.a[i] != 'object' ) {
- arr[i] = arg.a[i];
-
- } else if( typeof arg.a[i] == 'object'
- && arg.a[i]._isfieldmapper) {
-
- arr[i] = arg.a[i];
-
- } else {
- arr[i] = object2Array(arg.a[i]);
- }
- }
- arg.a = arr;
- }
-
- return "/*--S " + arg.classname + " --*/" + js2JSON(arg.a) + "/*--E " + arg.classname + " --*/";
-
- } else {
-
- if (arg.constructor == Array) {
- o = '';
- for (i = 0; i < arg.length; ++i) {
- v = js2JSON(arg[i]);
- if (o) {
- o += ',';
- }
- if (v !== u) {
- o += v;
- } else {
- o += 'null';
- }
- }
- return '[' + o + ']';
-
- } else if (typeof arg.toString != 'undefined') {
- o = '';
- for (i in arg) {
- v = js2JSON(arg[i]);
- if (v !== u) {
- if (o) {
- o += ',';
- }
- o += js2JSON(i) + ':' + v;
- }
- }
-
- o = '{' + o + '}';
- return o;
-
- } else {
- return;
- }
- }
- }
- return 'null';
-
- case 'unknown':
- case 'number':
- return arg;
-
- case 'undefined':
- case 'function':
- return u;
-
- case 'string':
- default:
- return '"' + String(arg).replace(/(["\\])/g, '\\$1') + '"';
- }
-
-}
Copied: branches/autotools/src/javascript/JSON_v0.js (from rev 1120, trunk/src/javascript/JSON_v0.js)
===================================================================
--- branches/autotools/src/javascript/JSON_v0.js (rev 0)
+++ branches/autotools/src/javascript/JSON_v0.js 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,135 @@
+// in case we run on an implimentation that doesn't have "undefined";
+var undefined;
+
+function Cast (obj, class_constructor) {
+ try {
+ if (eval(class_constructor + '["_isfieldmapper"]')) {
+ obj = eval("new " + class_constructor + "(obj)");
+ }
+ } catch( E ) {
+ alert( E + "\n");
+ } finally {
+ return obj;
+ }
+}
+
+function JSON2js (json) {
+
+ json = String(json).replace( /\/\*--\s*S\w*?\s*?\s+\w+\s*--\*\//g, 'Cast(');
+ json = String(json).replace( /\/\*--\s*E\w*?\s*?\s+(\w+)\s*--\*\//g, ', "$1")');
+
+ var obj;
+ if (json != '') {
+ try {
+ eval( 'obj = ' + json );
+ } catch(E) {
+ debug("Error building JSON object with string " + E + "\nString:\n" + json );
+ return null;
+ }
+ }
+ return obj;
+}
+
+
+function object2Array(obj) {
+ if( obj == null ) return null;
+
+ var arr = new Array();
+ for( var i = 0; i < obj.length; i++ ) {
+ arr[i] = obj[i];
+ }
+ return arr;
+}
+
+
+function js2JSON(arg) {
+ return _js2JSON(arg);
+}
+
+function _js2JSON(arg) {
+ var i, o, u, v;
+
+ switch (typeof arg) {
+ case 'object':
+
+ if(arg) {
+
+ if (arg._isfieldmapper) { /* magi-c-ast for fieldmapper objects */
+
+ if( arg.a.constructor != Array ) {
+ var arr = new Array();
+ for( var i = 0; i < arg.a.length; i++ ) {
+ if( arg.a[i] == null ) {
+ arr[i] = null; continue;
+ }
+
+ if( typeof arg.a[i] != 'object' ) {
+ arr[i] = arg.a[i];
+
+ } else if( typeof arg.a[i] == 'object'
+ && arg.a[i]._isfieldmapper) {
+
+ arr[i] = arg.a[i];
+
+ } else {
+ arr[i] = object2Array(arg.a[i]);
+ }
+ }
+ arg.a = arr;
+ }
+
+ return "/*--S " + arg.classname + " --*/" + js2JSON(arg.a) + "/*--E " + arg.classname + " --*/";
+
+ } else {
+
+ if (arg.constructor == Array) {
+ o = '';
+ for (i = 0; i < arg.length; ++i) {
+ v = js2JSON(arg[i]);
+ if (o) {
+ o += ',';
+ }
+ if (v !== u) {
+ o += v;
+ } else {
+ o += 'null';
+ }
+ }
+ return '[' + o + ']';
+
+ } else if (typeof arg.toString != 'undefined') {
+ o = '';
+ for (i in arg) {
+ v = js2JSON(arg[i]);
+ if (v !== u) {
+ if (o) {
+ o += ',';
+ }
+ o += js2JSON(i) + ':' + v;
+ }
+ }
+
+ o = '{' + o + '}';
+ return o;
+
+ } else {
+ return;
+ }
+ }
+ }
+ return 'null';
+
+ case 'unknown':
+ case 'number':
+ return arg;
+
+ case 'undefined':
+ case 'function':
+ return u;
+
+ case 'string':
+ default:
+ return '"' + String(arg).replace(/(["\\])/g, '\\$1') + '"';
+ }
+
+}
Copied: branches/autotools/src/javascript/JSON_v1.js (from rev 1120, trunk/src/javascript/JSON_v1.js)
===================================================================
--- branches/autotools/src/javascript/JSON_v1.js (rev 0)
+++ branches/autotools/src/javascript/JSON_v1.js 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,201 @@
+var JSON_CLASS_KEY = '__c';
+var JSON_DATA_KEY = '__p';
+
+
+
+function JSON_version() { return 'wrapper' }
+
+function JSON2js(text) {
+ return decodeJS(JSON2jsRaw(text));
+}
+
+function JSON2jsRaw(text) {
+ var obj;
+ eval('obj = ' + text);
+ return obj;
+}
+
+
+/* iterates over object, arrays, or fieldmapper objects */
+function jsIterate( arg, callback ) {
+ if( arg && typeof arg == 'object' ) {
+ if( arg.constructor == Array ) {
+ for( var i = 0; i < arg.length; i++ )
+ callback(arg, i);
+
+ } else if( arg.constructor == Object ) {
+ for( var i in arg )
+ callback(arg, i);
+
+ } else if( arg._isfieldmapper && arg.a ) {
+ for( var i = 0; i < arg.a.length; i++ )
+ callback(arg.a, i);
+ }
+ }
+}
+
+
+/* removes the class/paylod wrapper objects */
+function decodeJS(arg) {
+
+ if(arg == null) return null;
+
+ if( arg && typeof arg == 'object' &&
+ arg.constructor == Object &&
+ arg[JSON_CLASS_KEY] ) {
+ eval('arg = new ' + arg[JSON_CLASS_KEY] + '(arg[JSON_DATA_KEY])');
+ }
+
+ jsIterate( arg,
+ function(o, i) {
+ o[i] = decodeJS(o[i]);
+ }
+ );
+
+ return arg;
+}
+
+
+function jsClone(obj) {
+ if( obj == null ) return null;
+ if( typeof obj != 'object' ) return obj;
+
+ var newobj;
+ if (obj.constructor == Array) {
+ newobj = [];
+ for( var i = 0; i < obj.length; i++ )
+ newobj[i] = jsClone(obj[i]);
+
+ } else if( obj.constructor == Object ) {
+ newobj = {};
+ for( var i in obj )
+ newobj[i] = jsClone(obj[i]);
+
+ } else if( obj._isfieldmapper && obj.a ) {
+ eval('newobj = new '+obj.classname + '();');
+ for( var i = 0; i < obj.a.length; i++ )
+ newobj.a[i] = jsClone(obj.a[i]);
+ }
+
+ return newobj;
+}
+
+
+/* adds the class/paylod wrapper objects */
+function encodeJS(arg) {
+ if( arg == null ) return null;
+ if( typeof arg != 'object' ) return arg;
+
+ if( arg._isfieldmapper ) {
+ var newarr = []
+ if(!arg.a) arg.a = [];
+ for( var i = 0; i < arg.a.length; i++ )
+ newarr[i] = encodeJS(arg.a[i]);
+
+ var a = {};
+ a[JSON_CLASS_KEY] = arg.classname;
+ a[JSON_DATA_KEY] = newarr;
+ return a;
+ }
+
+ var newobj;
+
+ if(arg.length != undefined) {
+ newobj = [];
+ for( var i = 0; i < arg.length; i++ )
+ newobj.push(encodeJS(arg[i]));
+ return newobj;
+ }
+
+ newobj = {};
+ for( var i in arg )
+ newobj[i] = encodeJS(arg[i]);
+ return newobj;
+}
+
+/* turns a javascript object into a JSON string */
+function js2JSON(arg) {
+ return js2JSONRaw(encodeJS(arg));
+}
+
+function js2JSONRaw(arg) {
+
+ if( arg == null )
+ return 'null';
+
+ var o;
+
+ switch (typeof arg) {
+
+ case 'object':
+
+ if (arg.constructor == Array) {
+ o = '';
+ jsIterate( arg,
+ function(obj, i) {
+ if (o) o += ',';
+ o += js2JSONRaw(obj[i]);
+ }
+ );
+ return '[' + o + ']';
+
+ } else if (typeof arg.toString != 'undefined') {
+ o = '';
+ jsIterate( arg,
+ function(obj, i) {
+ if (o) o += ',';
+ o = o + js2JSONRaw(i) + ':' + js2JSONRaw(obj[i]);
+ }
+ );
+ return '{' + o + '}';
+
+ } else {
+ return 'null';
+ }
+
+ case 'number': return arg;
+
+ case 'string':
+ var s = String(arg);
+ s = s.replace(/\\/g, '\\\\');
+ s = s.replace(/"/g, '\\"');
+ s = s.replace(/\t/g, "\\t");
+ s = s.replace(/\n/g, "\\n");
+ s = s.replace(/\r/g, "\\r");
+ s = s.replace(/\f/g, "\\f");
+ return '"' + s + '"';
+
+ default: return 'null';
+ }
+}
+
+
+function __tabs(c) {
+ var s = '';
+ for( i = 0; i < c; i++ ) s += '\t';
+ return s;
+}
+
+function jsonPretty(str) {
+ if(!str) return "";
+ var s = '';
+ var d = 0;
+ for( var i = 0; i < str.length; i++ ) {
+ var c = str.charAt(i);
+ if( c == '{' || c == '[' ) {
+ s += c + '\n' + __tabs(++d);
+ } else if( c == '}' || c == ']' ) {
+ s += '\n' + __tabs(--d) + '\n';
+ if( str.charAt(i+1) == ',' ) {
+ s += '\n' + __tabs(d);
+ }
+ } else if( c == ',' ) {
+ s += ',\n' + __tabs(d);
+ } else {
+ s += c;
+ }
+ }
+ return s;
+}
+
+
Modified: branches/autotools/src/jserver/Makefile
===================================================================
--- branches/autotools/src/jserver/Makefile 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/jserver/Makefile 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,4 +1,4 @@
-LDLIBS += -lopensrf -lobjson -lxml2
+LDLIBS += -lopensrf -lxml2
CFLAGS += -D_GNU_SOURCE
all: chopchop
Modified: branches/autotools/src/jserver/osrf_chat.c
===================================================================
--- branches/autotools/src/jserver/osrf_chat.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/jserver/osrf_chat.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -279,7 +279,7 @@
int l = strlen(toAddr);
char dombuf[l];
- bzero(dombuf, l);
+ memset(dombuf, 0, sizeof(dombuf));
jid_get_domain( toAddr, dombuf, l );
if( eq( dombuf, cs->domain ) ) { /* this is to a user we host */
@@ -595,8 +595,7 @@
char* osrfChatMkAuthKey() {
char keybuf[112];
- bzero(keybuf, 112);
- snprintf(keybuf, 111, "%d%ld%s", (int) time(NULL), (long) getpid(), getenv("HOSTNAME"));
+ snprintf(keybuf, sizeof(keybuf), "%d%ld%s", (int) time(NULL), (long) getpid(), getenv("HOSTNAME"));
return strdup(shahash(keybuf));
}
Modified: branches/autotools/src/libopensrf/Makefile
===================================================================
--- branches/autotools/src/libopensrf/Makefile 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/Makefile 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,10 +1,17 @@
-# 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
+# ------------------------------------------------------------------
+# To build the standalone JSON lib libosrf_json.so:
+# $ make libosrf_json.so
+# To build the standalone JSON lib libosrf_json.so with XML utils
+# support, use something like the following:
+# $ CFLAGS="-DOSRF_JSON_ENABLE_XML_UTILS -I/usr/include/libxml2" LDLIBS=-lxml2 make libosrf_json.so
+#
+# The compiler flag -DOSRF_JSON_ALLOW_COMMENTS tells the parser to
+# allow legacy JSON comments like /* comment */
+# ------------------------------------------------------------------
-CFLAGS += -DASSUME_STATELESS -DOSRF_LOG_PARAMS -DOSRF_STRICT_PARAMS -rdynamic -fno-strict-aliasing
-LDLIBS += -lxml2 -lobjson -ldl -lmemcache
-OSRF_INC = ../../include/opensrf/
+CFLAGS += -DASSUME_STATELESS -DOSRF_STRICT_PARAMS -rdynamic -fno-strict-aliasing -I../../include -fPIC -Wall -DOSRF_JSON_ENABLE_XML_UTILS
+LDLIBS += -lxml2 -ldl -lmemcache
+export OSRF_INC = ../../include/opensrf/
TARGETS = osrf_message.o \
osrf_app_session.o \
@@ -27,12 +34,24 @@
utils.o\
socket_bundle.o\
sha.o\
- string_array.o
+ string_array.o
+JSON_TARGETS = osrf_json_object.o\
+ osrf_json_parser.o \
+ osrf_json_tools.o \
+ osrf_legacy_json.o \
+ osrf_json_xml.o
-all: opensrf
+# use these when building the standalone JSON module
+JSON_DEPS = osrf_list.o\
+ osrf_hash.o\
+ utils.o\
+ log.o\
+ md5.o\
+ string_array.o
+all: opensrf
# Build the OpenSRF C binary
opensrf: opensrf.o libopensrf.so
@@ -41,10 +60,28 @@
# Build the OpenSRF library
-libopensrf.so: $(TARGETS)
- $(CC) -shared -W1 $(LDFLAGS) $(LDLIBS) $(TARGETS) -o $(TMPDIR)/libopensrf.so
+libopensrf.so: $(TARGETS) json
+ if [ ! -z "$(OSRF_LEGACY_JSON)" ]; then\
+ $(CC) -shared -W1 $(LDFLAGS) $(LDLIBS) $(TARGETS) -o $(TMPDIR)/libopensrf.so;\
+ else\
+ $(CC) -shared -W1 $(LDFLAGS) $(LDLIBS) $(TARGETS) $(JSON_TARGETS) -o $(TMPDIR)/libopensrf.so;\
+ fi;
+json: $(JSON_TARGETS) $(JSON_DEPS)
+ if [ ! -z "$(OSRF_LEGACY_JSON)" ]; then \
+ $(CC) -shared -W1 $(CFLAGS) \
+ $(LDFLAGS) $(JSON_TARGETS) $(JSON_DEPS) -o $(TMPDIR)/libobjson.so;\
+ fi;
+
+libosrf_json.so: $(JSON_TARGETS) $(JSON_DEPS)
+ $(CC) -shared -W1 $(CFLAGS) \
+ $(LDFLAGS) $(LDLIBS) $(JSON_TARGETS) $(JSON_DEPS) -o $@
+
+
+osrf_json_test: osrf_json_test.o $(JSON_TARGETS) $(JSON_DEPS)
+
+
opensrf.o: opensrf.c
transport_message.o: transport_message.c $(OSRF_INC)/transport_message.h
transport_session.o: transport_session.c $(OSRF_INC)/transport_session.h
@@ -66,8 +103,17 @@
socket_bundle.o: socket_bundle.c $(OSRF_INC)/socket_bundle.h
sha.o: sha.c $(OSRF_INC)/sha.h
string_array.o: string_array.c $(OSRF_INC)/string_array.h
+osrf_json_object.o: osrf_json_object.c $(OSRF_INC)/osrf_json.h $(OSRF_INC)/osrf_json_utils.h
+osrf_json_parser.o: osrf_json_parser.c $(OSRF_INC)/osrf_json.h $(OSRF_INC)/osrf_json_utils.h
+osrf_json_tools.o: osrf_json_tools.c $(OSRF_INC)/osrf_json.h $(OSRF_INC)/osrf_json_utils.h
+osrf_legacy_json.o: osrf_legacy_json.c $(OSRF_INC)/osrf_json.h $(OSRF_INC)/osrf_json_utils.h
+osrf_json_xml.o: osrf_json_xml.c $(OSRF_INC)/osrf_json.h $(OSRF_INC)/osrf_json_xml.h
+osrf_json_test.o: osrf_json_test.c
clean:
- /bin/rm -f *.o libopensrf.so opensrf
+ /bin/rm -f *.o *.so opensrf osrf_json_test
+
+
+
Copied: branches/autotools/src/libopensrf/Makefile.json (from rev 1120, trunk/src/libopensrf/Makefile.json)
===================================================================
--- branches/autotools/src/libopensrf/Makefile.json (rev 0)
+++ branches/autotools/src/libopensrf/Makefile.json 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,40 @@
+#-DOSRF_JSON_ALLOW_COMMENTS
+
+# ------------------------------------------------------------------
+# To build a standalone version of libosrf_json, something
+# like the following should work:
+# $ CFLAGS="-fPIC -I /usr/include/libxml2 -I ../../include" \
+# OSRF_INC="../../include/opensrf" LDLIBS="-lxml2" \
+# make -f Makefile.json standalone
+# ------------------------------------------------------------------
+TARGETS = osrf_json_object.o osrf_json_parser.o osrf_json_tools.o osrf_legacy_json.o osrf_json_xml.o
+
+# these are only needed when compiling the standalone version
+EXT_TARGETS = osrf_list.o osrf_hash.o utils.o log.o md5.o string_array.o
+
+all: $(TARGETS)
+ if [ ! -z "$(OSRF_LEGACY_JSON)" ]; then \
+ $(CC) -shared -W1 $(LDFLAGS) $(TARGETS) -o $(TMPDIR)/libobjson.so;\
+ fi;
+
+standalone: $(TARGETS) $(EXT_TARGETS)
+ $(CC) -shared -W1 $(CFLAGS) $(LDFLAGS) $(LDLIBS) $(TARGETS) $(EXT_TARGETS) -o libosrf_json.so
+
+osrf_json_object.o: osrf_json_object.c $(OSRF_INC)/osrf_json.h $(OSRF_INC)/osrf_json_utils.h
+osrf_json_parser.o: osrf_json_parser.c $(OSRF_INC)/osrf_json.h $(OSRF_INC)/osrf_json_utils.h
+osrf_json_tools.o: osrf_json_tools.c $(OSRF_INC)/osrf_json.h $(OSRF_INC)/osrf_json_utils.h
+osrf_legacy_json.o: osrf_legacy_json.c $(OSRF_INC)/osrf_json.h $(OSRF_INC)/osrf_json_utils.h
+osrf_json_xml.o: osrf_json_xml.c $(OSRF_INC)/osrf_json.h $(OSRF_INC)/osrf_json_xml.h
+
+
+osrf_list.o: osrf_list.c $(OSRF_INC)/osrf_list.h
+osrf_hash.o: osrf_hash.c $(OSRF_INC)/osrf_hash.h
+utils.o: utils.c $(OSRF_INC)/utils.h
+md5.o: md5.c $(OSRF_INC)/md5.h
+log.o: log.c $(OSRF_INC)/log.h
+string_array.o: string_array.c $(OSRF_INC)/string_array.h
+
+
+clean:
+ rm -f osrf_json*.o osrf_legacy_json.o libosrf_json.so
+
Modified: branches/autotools/src/libopensrf/basic_client.c
===================================================================
--- branches/autotools/src/libopensrf/basic_client.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/basic_client.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -31,10 +31,10 @@
signal(SIGINT, sig_int);
fprintf(stderr, "Listener: %ld\n", (long) getpid() );
char buf[300];
- memset(buf, 0, 300);
+ osrf_clearbuf(buf, sizeof(buf));
printf("=> ");
- while( fgets( buf, 299, stdin) ) {
+ while( fgets( buf, sizeof(buf), stdin) ) {
// remove newline
buf[strlen(buf)-1] = '\0';
@@ -48,7 +48,7 @@
client_send_message( client, send );
message_free( send );
printf("\n=> ");
- memset(buf, 0, 300);
+ osrf_clearbuf(buf, sizeof(buf));
}
fprintf(stderr, "Killing child %d\n", pid );
kill( pid, SIGKILL );
Modified: branches/autotools/src/libopensrf/log.c
===================================================================
--- branches/autotools/src/libopensrf/log.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/log.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -58,8 +58,7 @@
if(_osrfLogIsClient) {
static int _osrfLogXidInc = 0; /* increments with each new xid for uniqueness */
char buf[32];
- memset(buf, 0x0, 32);
- snprintf(buf, 32, "%s%d", _osrfLogXidPfx, _osrfLogXidInc);
+ snprintf(buf, sizeof(buf), "%s%d", _osrfLogXidPfx, _osrfLogXidInc);
_osrfLogSetXid(buf);
_osrfLogXidInc++;
}
@@ -74,8 +73,7 @@
if(!is) return;
/* go ahead and create the xid prefix so it will be consistent later */
static char buff[32];
- memset(buff, 0x0, 32);
- snprintf(buff, 32, "%d%ld", (int)time(NULL), (long) getpid());
+ snprintf(buff, sizeof(buff), "%d%ld", (int)time(NULL), (long) getpid());
_osrfLogXidPfx = buff;
}
@@ -223,7 +221,7 @@
if( logtype == OSRF_LOG_TYPE_SYSLOG ) {
char buf[1536];
- memset(buf, 0x0, 1536);
+ osrf_clearbuf(buf, sizeof(buf));
/* give syslog some breathing room, and be cute about it */
strncat(buf, msg, 1535);
buf[1532] = '.';
Modified: branches/autotools/src/libopensrf/opensrf.c
===================================================================
--- branches/autotools/src/libopensrf/opensrf.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/opensrf.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -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[] ) {
Modified: branches/autotools/src/libopensrf/osrf_app_session.c
===================================================================
--- branches/autotools/src/libopensrf/osrf_app_session.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/osrf_app_session.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -4,7 +4,6 @@
/* the global app_session cache */
osrfHash* osrfAppSessionCache = NULL;
-
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// Request API
@@ -111,6 +110,11 @@
osrf_message* ret_msg = req->result;
osrf_message* tmp_msg = ret_msg->next;
req->result = tmp_msg;
+ if (ret_msg->sender_locale) {
+ if (req->session->session_locale)
+ free(req->session->session_locale);
+ req->session->session_locale = strdup(ret_msg->sender_locale);
+ }
return ret_msg;
}
@@ -125,6 +129,11 @@
osrf_message* ret_msg = req->result;
osrf_message* tmp_msg = ret_msg->next;
req->result = tmp_msg;
+ if (ret_msg->sender_locale) {
+ if (req->session->session_locale)
+ free(req->session->session_locale);
+ req->session->session_locale = strdup(ret_msg->sender_locale);
+ }
return ret_msg;
}
if( req->complete )
@@ -133,7 +142,7 @@
if(req->reset_timeout) {
remaining = (time_t) timeout;
req->reset_timeout = 0;
- osrfLogDebug( OSRF_LOG_MARK, "Recevied a timeout reset");
+ osrfLogDebug( OSRF_LOG_MARK, "Received a timeout reset");
} else {
remaining -= (int) (time(NULL) - start);
}
@@ -161,6 +170,18 @@
// --------------------------------------------------------------------------
/** returns a session from the global session hash */
+char* osrf_app_session_set_locale( osrf_app_session* session, const char* locale ) {
+ if (!session || !locale)
+ return NULL;
+
+ if(session->session_locale)
+ free(session->session_locale);
+
+ session->session_locale = strdup( locale );
+ return session->session_locale;
+}
+
+/** returns a session from the global session hash */
osrf_app_session* osrf_app_session_find_session( char* session_id ) {
if(session_id) return osrfHashGet(osrfAppSessionCache, session_id);
return NULL;
@@ -183,6 +204,11 @@
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();
@@ -192,15 +218,32 @@
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");
-
- int len = snprintf( target_buf, 512, "%s@%s/%s", router_name, domain, remote_service );
+ 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, sizeof(target_buf), "%s@%s/%s",
+ router_name ? router_name : "(null)",
+ domain ? domain : "(null)",
+ remote_service ? remote_service : "(null)" );
osrfStringArrayFree(arr);
//free(domain);
free(router_name);
@@ -216,6 +259,7 @@
session->remote_id = strdup(target_buf);
session->orig_remote_id = strdup(session->remote_id);
session->remote_service = strdup(remote_service);
+ session->session_locale = NULL;
#ifdef ASSUME_STATELESS
session->stateless = 1;
@@ -227,9 +271,8 @@
/* build a chunky, random session id */
char id[256];
- memset(id,0,256);
- sprintf(id, "%f.%d%ld", get_timestamp_millis(), (int)time(NULL), (long) getpid());
+ snprintf(id, sizeof(id), "%f.%d%ld", get_timestamp_millis(), (int)time(NULL), (long) getpid());
session->session_id = strdup(id);
osrfLogDebug( OSRF_LOG_MARK, "Building a new client session with id [%s] [%s]",
session->remote_service, session->session_id );
@@ -296,6 +339,9 @@
if( session->userDataFree && session->userData )
session->userDataFree(session->userData);
+ if(session->session_locale)
+ free(session->session_locale);
+
free(session->remote_id);
free(session->orig_remote_id);
free(session->session_id);
@@ -308,19 +354,42 @@
osrf_app_session* session, jsonObject* params,
char* method_name, int protocol, string_array* param_strings ) {
- return osrf_app_session_make_req( session, params,
- method_name, protocol, param_strings );
+ return osrf_app_session_make_locale_req( session, params,
+ method_name, protocol, param_strings, NULL );
}
+int osrfAppSessionMakeLocaleRequest(
+ osrf_app_session* session, jsonObject* params,
+ char* method_name, int protocol, string_array* param_strings, char* locale ) {
+
+ return osrf_app_session_make_locale_req( session, params,
+ method_name, protocol, param_strings, locale );
+}
+
int osrf_app_session_make_req(
osrf_app_session* session, jsonObject* params,
- char* method_name, int protocol, string_array* param_strings ) {
+ char* method_name, int protocol, string_array* param_strings) {
+
+ return osrf_app_session_make_locale_req(session, params,
+ method_name, protocol, param_strings, NULL);
+}
+
+int osrf_app_session_make_locale_req(
+ osrf_app_session* session, jsonObject* params,
+ char* method_name, int protocol, string_array* param_strings, char* locale ) {
if(session == NULL) return -1;
- osrfLogMkXid();
+ osrfLogMkXid();
osrf_message* req_msg = osrf_message_init( REQUEST, ++(session->thread_trace), protocol );
osrf_message_set_method(req_msg, method_name);
+
+ if (locale) {
+ osrf_message_set_locale(req_msg, locale);
+ } else if (session->session_locale) {
+ osrf_message_set_locale(req_msg, session->session_locale);
+ }
+
if(params) {
osrf_message_set_params(req_msg, params);
@@ -341,7 +410,7 @@
return -1;
}
- osrfLogDebug( OSRF_LOG_MARK, "Pushing [%d] onto requeust queue for session [%s] [%s]",
+ osrfLogDebug( OSRF_LOG_MARK, "Pushing [%d] onto request queue for session [%s] [%s]",
req->request_id, session->remote_service, session->session_id );
osrfListSet( session->request_queue, req, req->request_id );
return req->request_id;
Modified: branches/autotools/src/libopensrf/osrf_application.c
===================================================================
--- branches/autotools/src/libopensrf/osrf_application.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/osrf_application.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,11 +1,7 @@
#include <opensrf/osrf_application.h>
-#include <objson/object.h>
-//osrfApplication* __osrfAppList = NULL;
-
osrfHash* __osrfAppHash = NULL;
-
int osrfAppRegisterApplication( char* appName, char* soFile ) {
if(!appName || ! soFile) return -1;
char* error;
@@ -16,7 +12,7 @@
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() );
@@ -55,28 +51,27 @@
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);
}
@@ -106,14 +101,14 @@
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();
+ }
+ }
}
Modified: branches/autotools/src/libopensrf/osrf_cache.c
===================================================================
--- branches/autotools/src/libopensrf/osrf_cache.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/osrf_cache.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -96,4 +96,9 @@
return -1;
}
+void osrfCacheCleanup() {
+ if(__osrfCache)
+ mc_free(__osrfCache);
+}
+
Modified: branches/autotools/src/libopensrf/osrf_hash.c
===================================================================
--- branches/autotools/src/libopensrf/osrf_hash.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/osrf_hash.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -193,7 +193,7 @@
}
osrfListFree(hash->hash);
- osrfStringArrayFree(hash->keys);
+ OSRF_STRING_ARRAY_FREE(hash->keys);
free(hash);
}
@@ -201,7 +201,6 @@
osrfHashIterator* osrfNewHashIterator( osrfHash* hash ) {
if(!hash) return NULL;
- //osrfHashIterator* itr = safe_malloc(sizeof(osrfHashIterator));
osrfHashIterator* itr;
OSRF_MALLOC(itr, sizeof(osrfHashIterator));
itr->hash = hash;
@@ -214,8 +213,7 @@
if(!(itr && itr->hash)) return NULL;
if( itr->currentIdx >= itr->keys->size ) return NULL;
free(itr->current);
- itr->current = strdup(
- osrfStringArrayGetString(itr->keys, itr->currentIdx++));
+ itr->current = strdup(osrfStringArrayGetString(itr->keys, itr->currentIdx++));
char* val = osrfHashGet( itr->hash, itr->current );
return val;
}
@@ -223,14 +221,12 @@
void osrfHashIteratorFree( osrfHashIterator* itr ) {
if(!itr) return;
free(itr->current);
- //osrfStringArrayFree(itr->keys);
free(itr);
}
void osrfHashIteratorReset( osrfHashIterator* itr ) {
if(!itr) return;
free(itr->current);
- //osrfStringArrayFree(itr->keys);
itr->keys = osrfHashKeysInc(itr->hash);
itr->currentIdx = 0;
itr->current = NULL;
Copied: branches/autotools/src/libopensrf/osrf_json_object.c (from rev 1120, trunk/src/libopensrf/osrf_json_object.c)
===================================================================
--- branches/autotools/src/libopensrf/osrf_json_object.c (rev 0)
+++ branches/autotools/src/libopensrf/osrf_json_object.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,428 @@
+/*
+Copyright (C) 2006 Georgia Public Library Service
+Bill Erickson <billserickson at gmail.com>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+*/
+
+#include <limits.h>
+#include <opensrf/osrf_json.h>
+#include <opensrf/osrf_json_utils.h>
+
+/* cleans up an object if it is morphing another object, also
+ * verifies that the appropriate storage container exists where appropriate */
+#define JSON_INIT_CLEAR(_obj_, newtype) \
+ if( _obj_->type == JSON_HASH && newtype != JSON_HASH ) { \
+ osrfHashFree(_obj_->value.h); \
+ _obj_->value.h = NULL; \
+} else if( _obj_->type == JSON_ARRAY && newtype != JSON_ARRAY ) { \
+ osrfListFree(_obj_->value.l); \
+ _obj_->value.l = NULL; \
+} else if( _obj_->type == JSON_STRING && newtype != JSON_STRING ) { \
+ free(_obj_->value.s); \
+ _obj_->value.s = NULL; \
+} \
+ _obj_->type = newtype;\
+ if( newtype == JSON_HASH && _obj_->value.h == NULL ) { \
+ _obj_->value.h = osrfNewHash(); \
+ _obj_->value.h->freeItem = _jsonFreeHashItem; \
+} else if( newtype == JSON_ARRAY && _obj_->value.l == NULL ) { \
+ _obj_->value.l = osrfNewList(); \
+ _obj_->value.l->freeItem = _jsonFreeListItem;\
+}
+
+static void add_json_to_buffer( const jsonObject* obj, growing_buffer * buf );
+
+jsonObject* jsonNewObject(const char* data) {
+
+ jsonObject* o;
+ OSRF_MALLOC(o, sizeof(jsonObject));
+ o->type = JSON_NULL;
+
+ if(data) {
+ o->type = JSON_STRING;
+ o->value.s = strdup(data);
+ }
+
+ return o;
+}
+
+jsonObject* jsonNewObjectFmt(const char* data, ...) {
+
+ jsonObject* o;
+ OSRF_MALLOC(o, sizeof(jsonObject));
+ o->type = JSON_NULL;
+
+ if(data) {
+ VA_LIST_TO_STRING(data);
+ o->type = JSON_STRING;
+ o->value.s = strdup(VA_BUF);
+ }
+
+ return o;
+}
+
+jsonObject* jsonNewNumberObject( double num ) {
+ jsonObject* o = jsonNewObject(NULL);
+ o->type = JSON_NUMBER;
+ o->value.n = num;
+ return o;
+}
+
+jsonObject* jsonNewBoolObject(int val) {
+ jsonObject* o = jsonNewObject(NULL);
+ o->type = JSON_BOOL;
+ jsonSetBool(o, val);
+ return o;
+}
+
+jsonObject* jsonNewObjectType(int type) {
+ jsonObject* o = jsonNewObject(NULL);
+ o->type = type;
+ return o;
+}
+
+void jsonObjectFree( jsonObject* o ) {
+
+ if(!o || o->parent) return;
+ free(o->classname);
+
+ switch(o->type) {
+ case JSON_HASH : osrfHashFree(o->value.h); break;
+ case JSON_ARRAY : osrfListFree(o->value.l); break;
+ case JSON_STRING : free(o->value.s); break;
+ }
+ free(o);
+}
+
+static void _jsonFreeHashItem(char* key, void* item){
+ if(!item) return;
+ jsonObject* o = (jsonObject*) item;
+ o->parent = NULL; /* detach the item */
+ jsonObjectFree(o);
+}
+static void _jsonFreeListItem(void* item){
+ if(!item) return;
+ jsonObject* o = (jsonObject*) item;
+ o->parent = NULL; /* detach the item */
+ jsonObjectFree(o);
+}
+
+void jsonSetBool(jsonObject* bl, int val) {
+ if(!bl) return;
+ JSON_INIT_CLEAR(bl, JSON_BOOL);
+ bl->value.b = val;
+}
+
+unsigned long jsonObjectPush(jsonObject* o, jsonObject* newo) {
+ if(!o) return -1;
+ if(!newo) newo = jsonNewObject(NULL);
+ JSON_INIT_CLEAR(o, JSON_ARRAY);
+ newo->parent = o;
+ osrfListPush( o->value.l, newo );
+ o->size = o->value.l->size;
+ return o->size;
+}
+
+unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj) {
+ if(!dest) return -1;
+ if(!newObj) newObj = jsonNewObject(NULL);
+ JSON_INIT_CLEAR(dest, JSON_ARRAY);
+ newObj->parent = dest;
+ osrfListSet( dest->value.l, newObj, index );
+ dest->size = dest->value.l->size;
+ return dest->value.l->size;
+}
+
+unsigned long jsonObjectSetKey( jsonObject* o, const char* key, jsonObject* newo) {
+ if(!o) return -1;
+ if(!newo) newo = jsonNewObject(NULL);
+ JSON_INIT_CLEAR(o, JSON_HASH);
+ newo->parent = o;
+ osrfHashSet( o->value.h, newo, key );
+ o->size = o->value.h->size;
+ return o->size;
+}
+
+jsonObject* jsonObjectGetKey( const jsonObject* obj, const char* key ) {
+ if(!(obj && obj->type == JSON_HASH && obj->value.h && key)) return NULL;
+ return osrfHashGet( obj->value.h, key);
+}
+
+const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key ) {
+ if(!(obj && obj->type == JSON_HASH && obj->value.h && key)) return NULL;
+ return osrfHashGet( obj->value.h, key);
+}
+
+char* jsonObjectToJSON( const jsonObject* obj ) {
+ jsonObject* obj2 = jsonObjectEncodeClass( obj );
+ char* json = jsonObjectToJSONRaw(obj2);
+ jsonObjectFree(obj2);
+ return json;
+}
+
+char* jsonObjectToJSONRaw( const jsonObject* obj ) {
+ if(!obj) return NULL;
+ growing_buffer* buf = buffer_init(32);
+ add_json_to_buffer( obj, buf );
+ return buffer_release( buf );
+}
+
+static void add_json_to_buffer( const jsonObject* obj, growing_buffer * buf ) {
+
+ switch(obj->type) {
+
+ case JSON_BOOL :
+ if(obj->value.b) OSRF_BUFFER_ADD(buf, "true");
+ else OSRF_BUFFER_ADD(buf, "false");
+ break;
+
+ case JSON_NUMBER: {
+ double x = obj->value.n;
+ if( x <= INT_MAX && x >= INT_MIN && x == (int) x ) {
+ INT_TO_STRING((int)x);
+ OSRF_BUFFER_ADD(buf, INTSTR);
+
+ } else {
+ DOUBLE_TO_STRING(x);
+ OSRF_BUFFER_ADD(buf, DOUBLESTR);
+ }
+ break;
+ }
+
+ case JSON_NULL:
+ OSRF_BUFFER_ADD(buf, "null");
+ break;
+
+ case JSON_STRING:
+ OSRF_BUFFER_ADD_CHAR(buf, '"');
+ char* data = obj->value.s;
+ int len = strlen(data);
+
+ char* output = uescape(data, len, 1);
+ OSRF_BUFFER_ADD(buf, output);
+ free(output);
+ OSRF_BUFFER_ADD_CHAR(buf, '"');
+ break;
+
+ case JSON_ARRAY: {
+ OSRF_BUFFER_ADD_CHAR(buf, '[');
+ if( obj->value.l ) {
+ int i;
+ for( i = 0; i != obj->value.l->size; i++ ) {
+ if(i > 0) OSRF_BUFFER_ADD(buf, ",");
+ add_json_to_buffer( OSRF_LIST_GET_INDEX(obj->value.l, i), buf );
+ }
+ }
+ OSRF_BUFFER_ADD_CHAR(buf, ']');
+ break;
+ }
+
+ case JSON_HASH: {
+
+ OSRF_BUFFER_ADD_CHAR(buf, '{');
+ osrfHashIterator* itr = osrfNewHashIterator(obj->value.h);
+ jsonObject* item;
+ int i = 0;
+
+ while( (item = osrfHashIteratorNext(itr)) ) {
+ if(i++ > 0) OSRF_BUFFER_ADD(buf, ",");
+ buffer_fadd(buf, "\"%s\":", itr->current);
+ add_json_to_buffer( item, buf );
+ }
+
+ osrfHashIteratorFree(itr);
+ OSRF_BUFFER_ADD_CHAR(buf, '}');
+ break;
+ }
+ }
+}
+
+
+jsonIterator* jsonNewIterator(const jsonObject* obj) {
+ if(!obj) return NULL;
+ jsonIterator* itr;
+ OSRF_MALLOC(itr, sizeof(jsonIterator));
+
+ itr->obj = (jsonObject*) obj;
+ itr->index = 0;
+ itr->key = NULL;
+
+ if( obj->type == JSON_HASH )
+ itr->hashItr = osrfNewHashIterator(obj->value.h);
+
+ return itr;
+}
+
+void jsonIteratorFree(jsonIterator* itr) {
+ if(!itr) return;
+ free(itr->key);
+ osrfHashIteratorFree(itr->hashItr);
+ free(itr);
+}
+
+jsonObject* jsonIteratorNext(jsonIterator* itr) {
+ if(!(itr && itr->obj)) return NULL;
+ if( itr->obj->type == JSON_HASH ) {
+ if(!itr->hashItr) return NULL;
+ jsonObject* item = osrfHashIteratorNext(itr->hashItr);
+ free(itr->key);
+ itr->key = strdup(itr->hashItr->current);
+ return item;
+ } else {
+ return jsonObjectGetIndex( itr->obj, itr->index++ );
+ }
+}
+
+int jsonIteratorHasNext(const jsonIterator* itr) {
+ if(!(itr && itr->obj)) return 0;
+ if( itr->obj->type == JSON_HASH )
+ return osrfHashIteratorHasNext( itr->hashItr );
+ return (itr->index < itr->obj->size) ? 1 : 0;
+}
+
+jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index ) {
+ if(!obj) return NULL;
+ return (obj->type == JSON_ARRAY) ?
+ (OSRF_LIST_GET_INDEX(obj->value.l, index)) : NULL;
+}
+
+
+
+unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index) {
+ if( dest && dest->type == JSON_ARRAY ) {
+ osrfListRemove(dest->value.l, index);
+ return dest->value.l->size;
+ }
+ return -1;
+}
+
+
+unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key) {
+ if( dest && key && dest->type == JSON_HASH ) {
+ osrfHashRemove(dest->value.h, key);
+ return 1;
+ }
+ return -1;
+}
+
+char* jsonObjectGetString(const jsonObject* obj) {
+ return (obj && obj->type == JSON_STRING) ? obj->value.s : NULL;
+}
+
+double jsonObjectGetNumber( const jsonObject* obj ) {
+ return (obj && obj->type == JSON_NUMBER) ? obj->value.n : 0;
+}
+
+void jsonObjectSetString(jsonObject* dest, const char* string) {
+ if(!(dest && string)) return;
+ JSON_INIT_CLEAR(dest, JSON_STRING);
+ free(dest->value.s);
+ dest->value.s = strdup(string);
+}
+
+void jsonObjectSetNumber(jsonObject* dest, double num) {
+ if(!dest) return;
+ JSON_INIT_CLEAR(dest, JSON_NUMBER);
+ dest->value.n = num;
+}
+
+void jsonObjectSetClass(jsonObject* dest, const char* classname ) {
+ if(!(dest && classname)) return;
+ free(dest->classname);
+ dest->classname = strdup(classname);
+}
+const char* jsonObjectGetClass(const jsonObject* dest) {
+ if(!dest) return NULL;
+ return dest->classname;
+}
+
+jsonObject* jsonObjectClone( const jsonObject* o ) {
+ if(!o) return jsonNewObject(NULL);
+
+ int i;
+ jsonObject* arr;
+ jsonObject* hash;
+ jsonIterator* itr;
+ jsonObject* tmp;
+ jsonObject* result = NULL;
+
+ switch(o->type) {
+ case JSON_NULL:
+ result = jsonNewObject(NULL);
+ break;
+ case JSON_STRING:
+ result = jsonNewObject(jsonObjectGetString(o));
+ break;
+ case JSON_NUMBER:
+ result = jsonNewNumberObject(jsonObjectGetNumber(o));
+ break;
+ case JSON_BOOL:
+ result = jsonNewBoolObject(jsonBoolIsTrue((jsonObject*) o));
+ break;
+ case JSON_ARRAY:
+ arr = jsonNewObject(NULL);
+ arr->type = JSON_ARRAY;
+ for(i=0; i < o->size; i++)
+ jsonObjectPush(arr, jsonObjectClone(jsonObjectGetIndex(o, i)));
+ result = arr;
+ break;
+ case JSON_HASH:
+ hash = jsonNewObject(NULL);
+ hash->type = JSON_HASH;
+ itr = jsonNewIterator(o);
+ while( (tmp = jsonIteratorNext(itr)) )
+ jsonObjectSetKey(hash, itr->key, jsonObjectClone(tmp));
+ jsonIteratorFree(itr);
+ result = hash;
+ break;
+ }
+
+ jsonObjectSetClass(result, jsonObjectGetClass(o));
+ return result;
+}
+
+int jsonBoolIsTrue( jsonObject* boolObj ) {
+ if( boolObj && boolObj->type == JSON_BOOL && boolObj->value.b )
+ return 1;
+ return 0;
+}
+
+
+char* jsonObjectToSimpleString( const jsonObject* o ) {
+ if(!o) return NULL;
+
+ char* value = NULL;
+
+ switch( o->type ) {
+
+ case JSON_NUMBER: {
+
+ if( o->value.n == (int) o->value.n ) {
+ INT_TO_STRING((int) o->value.n);
+ value = strdup(INTSTR);
+
+ } else {
+ DOUBLE_TO_STRING(o->value.n);
+ value = strdup(DOUBLESTR);
+ }
+
+ break;
+ }
+
+ case JSON_STRING:
+ value = strdup(o->value.s);
+ }
+
+ return value;
+}
+
+
Copied: branches/autotools/src/libopensrf/osrf_json_parser.c (from rev 1120, trunk/src/libopensrf/osrf_json_parser.c)
===================================================================
--- branches/autotools/src/libopensrf/osrf_json_parser.c (rev 0)
+++ branches/autotools/src/libopensrf/osrf_json_parser.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,632 @@
+/*
+Copyright (C) 2006 Georgia Public Library Service
+Bill Erickson <billserickson at gmail.com>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+*/
+
+#include <opensrf/osrf_json.h>
+#include <opensrf/osrf_json_utils.h>
+#include <ctype.h>
+
+
+/* if the client sets a global error handler, this will point to it */
+static void (*jsonClientErrorCallback) (const char*) = NULL;
+
+/* these are the handlers for our internal parser */
+static jsonParserHandler jsonInternalParserHandlerStruct = {
+ _jsonHandleStartObject,
+ _jsonHandleObjectKey,
+ _jsonHandleEndObject,
+ _jsonHandleStartArray,
+ _jsonHandleEndArray,
+ _jsonHandleNull,
+ _jsonHandleString,
+ _jsonHandleBool,
+ _jsonHandleNumber,
+ _jsonHandleError
+};
+static jsonParserHandler*
+ jsonInternalParserHandler = &jsonInternalParserHandlerStruct;
+
+
+jsonParserContext* jsonNewParser( jsonParserHandler* handler, void* userData) {
+ jsonParserContext* ctx;
+ OSRF_MALLOC(ctx, sizeof(jsonParserContext));
+ ctx->stateStack = osrfNewList();
+ ctx->buffer = buffer_init(512);
+ ctx->utfbuf = buffer_init(5);
+ ctx->handler = handler;
+ ctx->state = 0;
+ ctx->index = 0;
+ ctx->chunk = NULL;
+ ctx->userData = userData;
+ return ctx;
+}
+
+void jsonParserFree( jsonParserContext* ctx ) {
+ if(!ctx) return;
+ buffer_free(ctx->buffer);
+ buffer_free(ctx->utfbuf);
+ osrfListFree(ctx->stateStack);
+ free(ctx);
+}
+
+
+void jsonSetGlobalErrorHandler(void (*errorHandler) (const char*)) {
+ jsonClientErrorCallback = errorHandler;
+}
+
+
+int _jsonParserError( jsonParserContext* ctx, char* err, ... ) {
+ if( ctx->handler->handleError ) {
+ VA_LIST_TO_STRING(err);
+ int pre = ctx->index - 15;
+ int post= ctx->index + 15;
+ while( pre < 0 ) pre++;
+ while( post >= ctx->chunksize ) post--;
+ int l = post - pre;
+ char buf[l];
+ snprintf(buf, sizeof(buf), ctx->chunk + pre);
+ ctx->handler->handleError( ctx->userData,
+ "*JSON Parser Error\n - char = %c\n "
+ "- index = %d\n - near => %s\n - %s",
+ ctx->chunk[ctx->index], ctx->index, buf, VA_BUF );
+ }
+ JSON_STATE_SET(ctx, JSON_STATE_IS_INVALID);
+ return -1;
+}
+
+
+int _jsonParserHandleUnicode( jsonParserContext* ctx ) {
+
+ /* collect as many of the utf characters as we can in this chunk */
+ JSON_CACHE_DATA(ctx, ctx->utfbuf, 4);
+
+ /* we ran off the end of the chunk */
+ if( ctx->utfbuf->n_used < 4 ) {
+ JSON_STATE_SET(ctx, JSON_STATE_IN_UTF);
+ return 1;
+ }
+
+ ctx->index--; /* push it back to index of the final utf char */
+
+ /* ----------------------------------------------------------------------- */
+ /* We have all of the escaped unicode data. Write it to the buffer */
+ /* The following chunk is used with permission from
+ * json-c http://oss.metaparadigm.com/json-c/
+ */
+ #define hexdigit(x) ( ((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
+ unsigned char utf_out[4];
+ memset(utf_out, 0, sizeof(utf_out));
+ char* buf = ctx->utfbuf->buf;
+
+ unsigned int ucs_char =
+ (hexdigit(buf[0] ) << 12) +
+ (hexdigit(buf[1]) << 8) +
+ (hexdigit(buf[2]) << 4) +
+ hexdigit(buf[3]);
+
+ if (ucs_char < 0x80) {
+ utf_out[0] = ucs_char;
+ OSRF_BUFFER_ADD(ctx->buffer, (char*)utf_out);
+
+ } else if (ucs_char < 0x800) {
+ utf_out[0] = 0xc0 | (ucs_char >> 6);
+ utf_out[1] = 0x80 | (ucs_char & 0x3f);
+ OSRF_BUFFER_ADD(ctx->buffer, (char*)utf_out);
+
+ } else {
+ utf_out[0] = 0xe0 | (ucs_char >> 12);
+ utf_out[1] = 0x80 | ((ucs_char >> 6) & 0x3f);
+ utf_out[2] = 0x80 | (ucs_char & 0x3f);
+ OSRF_BUFFER_ADD(ctx->buffer, (char*)utf_out);
+ }
+ /* ----------------------------------------------------------------------- */
+ /* ----------------------------------------------------------------------- */
+
+ JSON_STATE_REMOVE(ctx, JSON_STATE_IN_UTF);
+ JSON_STATE_REMOVE(ctx, JSON_STATE_IN_ESCAPE);
+ OSRF_BUFFER_RESET(ctx->utfbuf);
+ return 0;
+}
+
+
+
+/* type : 0=null, 1=true, 2=false */
+int _jsonParserHandleMatch( jsonParserContext* ctx, int type ) {
+
+ switch(type) {
+
+ case 0: /* JSON null */
+
+ /* first see if we have it all first */
+ if( ctx->chunksize > (ctx->index + 3) ) {
+ if( strncasecmp(ctx->chunk + ctx->index, "null", 4) )
+ return _jsonParserError(ctx, "Invalid JSON 'null' sequence");
+ if( ctx->handler->handleNull )
+ ctx->handler->handleNull(ctx->userData);
+ ctx->index += 4;
+ break;
+ }
+
+ JSON_CACHE_DATA(ctx, ctx->buffer, 4);
+ if( ctx->buffer->n_used < 4 ) {
+ JSON_STATE_SET(ctx, JSON_STATE_IN_NULL);
+ return 1;
+ }
+
+ if( strncasecmp(ctx->buffer->buf, "null", 4) )
+ return _jsonParserError(ctx, "Invalid JSON 'null' sequence");
+ if( ctx->handler->handleNull )
+ ctx->handler->handleNull(ctx->userData);
+ break;
+
+ case 1: /* JSON true */
+
+ /* see if we have it all first */
+ if( ctx->chunksize > (ctx->index + 3) ) {
+ if( strncasecmp(ctx->chunk + ctx->index, "true", 4) )
+ return _jsonParserError(ctx, "Invalid JSON 'true' sequence");
+ if( ctx->handler->handleBool )
+ ctx->handler->handleBool(ctx->userData, 1);
+ ctx->index += 4;
+ break;
+ }
+
+ JSON_CACHE_DATA(ctx, ctx->buffer, 4);
+ if( ctx->buffer->n_used < 4 ) {
+ JSON_STATE_SET(ctx, JSON_STATE_IN_TRUE);
+ return 1;
+ }
+ if( strncasecmp( ctx->buffer->buf, "true", 4 ) ) {
+ return _jsonParserError(ctx, "Invalid JSON 'true' sequence");
+ }
+ if( ctx->handler->handleBool )
+ ctx->handler->handleBool(ctx->userData, 1);
+ break;
+
+ case 2: /* JSON false */
+
+ /* see if we have it all first */
+ if( ctx->chunksize > (ctx->index + 4) ) {
+ if( strncasecmp(ctx->chunk + ctx->index, "false", 5) )
+ return _jsonParserError(ctx, "Invalid JSON 'false' sequence");
+ if( ctx->handler->handleBool )
+ ctx->handler->handleBool(ctx->userData, 0);
+ ctx->index += 5;
+ break;
+ }
+
+ JSON_CACHE_DATA(ctx, ctx->buffer, 5);
+ if( ctx->buffer->n_used < 5 ) {
+ JSON_STATE_SET(ctx, JSON_STATE_IN_FALSE);
+ return 1;
+ }
+ if( strncasecmp( ctx->buffer->buf, "false", 5 ) )
+ return _jsonParserError(ctx, "Invalid JSON 'false' sequence");
+ if( ctx->handler->handleBool )
+ ctx->handler->handleBool(ctx->userData, 0);
+ break;
+
+ default:
+ fprintf(stderr, "Invalid type flag\n");
+ return -1;
+
+ }
+
+ ctx->index--; /* set it back to the index of the final sequence character */
+ OSRF_BUFFER_RESET(ctx->buffer);
+ JSON_STATE_REMOVE(ctx, JSON_STATE_IN_NULL);
+ JSON_STATE_REMOVE(ctx, JSON_STATE_IN_TRUE);
+ JSON_STATE_REMOVE(ctx, JSON_STATE_IN_FALSE);
+
+ return 0;
+}
+
+
+int _jsonParserHandleString( jsonParserContext* ctx ) {
+
+ char c = ctx->chunk[ctx->index];
+
+ if( JSON_STATE_CHECK(ctx, JSON_STATE_IN_ESCAPE) ) {
+
+ if( JSON_STATE_CHECK(ctx, JSON_STATE_IN_UTF) ) {
+
+ return _jsonParserHandleUnicode( ctx );
+
+ } else {
+
+ switch(c) {
+
+ /* handle all of the escape chars */
+ case '\\': OSRF_BUFFER_ADD_CHAR( ctx->buffer, '\\' ); break;
+ case '"' : OSRF_BUFFER_ADD_CHAR( ctx->buffer, '\"' ); break;
+ case 't' : OSRF_BUFFER_ADD_CHAR( ctx->buffer, '\t' ); break;
+ case 'b' : OSRF_BUFFER_ADD_CHAR( ctx->buffer, '\b' ); break;
+ case 'f' : OSRF_BUFFER_ADD_CHAR( ctx->buffer, '\f' ); break;
+ case 'r' : OSRF_BUFFER_ADD_CHAR( ctx->buffer, '\r' ); break;
+ case 'n' : OSRF_BUFFER_ADD_CHAR( ctx->buffer, '\n' ); break;
+ case 'u' :
+ ctx->index++; /* progress to the first utf char */
+ return _jsonParserHandleUnicode( ctx );
+ default : OSRF_BUFFER_ADD_CHAR( ctx->buffer, c );
+ }
+ }
+
+ JSON_STATE_REMOVE(ctx, JSON_STATE_IN_ESCAPE);
+ return 0;
+
+ } else {
+
+ switch(c) {
+
+ case '"' : /* this string is ending */
+ if( JSON_STATE_CHECK(ctx, JSON_STATE_IN_KEY) ) {
+
+ /* object key */
+ if(ctx->handler->handleObjectKey) {
+ ctx->handler->handleObjectKey(
+ ctx->userData, ctx->buffer->buf);
+ }
+
+ } else { /* regular json string */
+
+ if(ctx->handler->handleString) {
+ ctx->handler->handleString(
+ ctx->userData, ctx->buffer->buf );
+ }
+
+ }
+
+ OSRF_BUFFER_RESET(ctx->buffer); /* flush the buffer and states */
+ JSON_STATE_REMOVE(ctx, JSON_STATE_IN_STRING);
+ JSON_STATE_REMOVE(ctx, JSON_STATE_IN_KEY);
+ break;
+
+ case '\\' : JSON_STATE_SET(ctx, JSON_STATE_IN_ESCAPE); break;
+ default : OSRF_BUFFER_ADD_CHAR( ctx->buffer, c );
+ }
+ }
+ return 0;
+}
+
+
+int _jsonParserHandleNumber( jsonParserContext* ctx ) {
+ char c = ctx->chunk[ctx->index];
+
+ do {
+ OSRF_BUFFER_ADD_CHAR(ctx->buffer, c);
+ c = ctx->chunk[++(ctx->index)];
+ } while( strchr(JSON_NUMBER_CHARS, c) && ctx->index < ctx->chunksize );
+
+ /* if we're run off the end of the chunk and we're not parsing the last chunk,
+ * save the number and the state */
+ if( ctx->index >= ctx->chunksize &&
+ ! JSON_PARSE_FLAG_CHECK(ctx, JSON_PARSE_LAST_CHUNK) ) {
+ JSON_STATE_SET(ctx, JSON_STATE_IN_NUMBER);
+ return 1;
+ }
+
+ /* make me more strict */
+ char* err = NULL;
+ double d = strtod(ctx->buffer->buf, &err);
+ if(err && err[0] != '\0')
+ return _jsonParserError(ctx, "Invalid number sequence");
+ JSON_STATE_REMOVE(ctx, JSON_STATE_IN_NUMBER);
+ OSRF_BUFFER_RESET(ctx->buffer);
+ if(ctx->handler->handleNumber)
+ ctx->handler->handleNumber( ctx->userData, d );
+ ctx->index--; /* scooch back to the first non-digit number */
+ return 0;
+}
+
+
+
+
+int jsonParseChunk( jsonParserContext* ctx, const char* data, int datalen, int flags ) {
+
+ if( !( ctx && ctx->handler && data && datalen > 0 )) return -1;
+ ctx->chunksize = datalen;
+ ctx->chunk = data;
+ ctx->flags = flags;
+ char c;
+
+ if( JSON_STATE_CHECK(ctx, JSON_STATE_IS_INVALID) )
+ return _jsonParserError( ctx, "JSON Parser cannot continue after an error" );
+
+ if( JSON_STATE_CHECK(ctx, JSON_STATE_IS_DONE) )
+ return _jsonParserError( ctx, "Extra content at end of JSON data" );
+
+ for( ctx->index = 0; (ctx->index < ctx->chunksize) &&
+ (c = ctx->chunk[ctx->index]); ctx->index++ ) {
+
+ /* middle of parsing a string */
+ if( JSON_STATE_CHECK(ctx, JSON_STATE_IN_STRING)) {
+ if( _jsonParserHandleString(ctx) == -1 )
+ return -1;
+ continue;
+ }
+
+ /* middle of parsing a number */
+ if( JSON_STATE_CHECK(ctx, JSON_STATE_IN_NUMBER) ) {
+ if( _jsonParserHandleNumber(ctx) == -1 )
+ return -1;
+ continue;
+ }
+
+
+#ifdef OSRF_JSON_ALLOW_COMMENTS
+ /* we just saw a bare '/' character */
+ if( JSON_STATE_CHECK(ctx, JSON_STATE_START_COMMENT) ) {
+ if(c == '*') {
+ JSON_STATE_REMOVE(ctx, JSON_STATE_START_COMMENT);
+ JSON_STATE_SET(ctx, JSON_STATE_IN_COMMENT);
+ continue;
+ } else {
+ return _jsonParserError( ctx, "Invalid comment initializer" );
+ }
+ }
+
+ /* we're currently in the middle of a comment block */
+ if( JSON_STATE_CHECK(ctx, JSON_STATE_IN_COMMENT) ) {
+ if(c == '*') {
+ JSON_STATE_REMOVE(ctx, JSON_STATE_IN_COMMENT);
+ JSON_STATE_SET(ctx, JSON_STATE_END_COMMENT);
+ continue;
+ } else {
+ continue;
+ }
+ }
+
+ /* we're in a comment, and we just saw a '*' character */
+ if( JSON_STATE_CHECK(ctx, JSON_STATE_END_COMMENT) ) {
+ if( c == '/' ) { /* comment is finished */
+ JSON_STATE_REMOVE(ctx, JSON_STATE_END_COMMENT);
+ continue;
+ } else {
+ /* looks like this isn't the end of the comment after all */
+ JSON_STATE_SET(ctx, JSON_STATE_IN_COMMENT);
+ JSON_STATE_REMOVE(ctx, JSON_STATE_END_COMMENT);
+ }
+ }
+#endif
+
+ /* if we're in the middle of parsing a null/true/false sequence */
+ if( JSON_STATE_CHECK(ctx, (JSON_STATE_IN_NULL |
+ JSON_STATE_IN_TRUE | JSON_STATE_IN_FALSE)) ) {
+
+ int type = (JSON_STATE_CHECK(ctx, JSON_STATE_IN_NULL)) ? 0 :
+ (JSON_STATE_CHECK(ctx, JSON_STATE_IN_TRUE)) ? 1 : 2;
+
+ if( _jsonParserHandleMatch( ctx, type ) == -1 )
+ return -1;
+ continue;
+ }
+
+ JSON_EAT_WS(ctx);
+
+ /* handle all of the top level characters */
+ switch(c) {
+
+ case '{' : /* starting an object */
+ if( ctx->handler->handleStartObject)
+ ctx->handler->handleStartObject( ctx->userData );
+ JSON_STATE_PUSH(ctx, JSON_STATE_IN_OBJECT);
+ JSON_STATE_SET(ctx, JSON_STATE_IN_KEY);
+ break;
+
+ case '}' : /* ending an object */
+ if( ctx->handler->handleEndObject)
+ ctx->handler->handleEndObject( ctx->userData );
+ JSON_STATE_REMOVE(ctx, JSON_STATE_IN_KEY);
+ JSON_STATE_POP(ctx);
+ if( JSON_STATE_PEEK(ctx) == NULL )
+ JSON_STATE_SET(ctx, JSON_STATE_IS_DONE);
+ break;
+
+ case '[' : /* starting an array */
+ if( ctx->handler->handleStartArray )
+ ctx->handler->handleStartArray( ctx->userData );
+ JSON_STATE_PUSH(ctx, JSON_STATE_IN_ARRAY);
+ break;
+
+ case ']': /* ending an array */
+ if( ctx->handler->handleEndArray )
+ ctx->handler->handleEndArray( ctx->userData );
+ JSON_STATE_POP(ctx);
+ if( JSON_STATE_PEEK(ctx) == NULL )
+ JSON_STATE_SET(ctx, JSON_STATE_IS_DONE);
+ break;
+
+ case ':' : /* done with the object key */
+ JSON_STATE_REMOVE(ctx, JSON_STATE_IN_KEY);
+ break;
+
+ case ',' : /* after object or array item */
+ if( JSON_STATE_CHECK_STACK(ctx, JSON_STATE_IN_OBJECT) )
+ JSON_STATE_SET(ctx, JSON_STATE_IN_KEY);
+ break;
+
+ case 'n' :
+ case 'N' : /* null */
+ if( _jsonParserHandleMatch( ctx, 0 ) == -1)
+ return -1;
+ break;
+
+ case 't' :
+ case 'T' :
+ if( _jsonParserHandleMatch( ctx, 1 ) == -1 )
+ return -1;
+ break;
+
+ case 'f' :
+ case 'F' :
+ if( _jsonParserHandleMatch( ctx, 2 ) == -1)
+ return -1;
+ break;
+
+ case '"' :
+ JSON_STATE_SET(ctx, JSON_STATE_IN_STRING);
+ break;
+
+#ifdef OSRF_JSON_ALLOW_COMMENTS
+ case '/' :
+ JSON_STATE_SET(ctx, JSON_STATE_START_COMMENT);
+ break;
+#endif
+
+ default:
+ if( strchr(JSON_NUMBER_CHARS, c) ) {
+ if( _jsonParserHandleNumber( ctx ) == -1 )
+ return -1;
+ } else {
+ return _jsonParserError( ctx, "Invalid Token" );
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+jsonInternalParser* _jsonNewInternalParser() {
+ jsonInternalParser* p;
+ OSRF_MALLOC(p, sizeof(jsonInternalParser));
+ p->ctx = jsonNewParser( jsonInternalParserHandler, p );
+ p->obj = NULL;
+ p->lastkey = NULL;
+ return p;
+}
+
+void _jsonInternalParserFree(jsonInternalParser* p) {
+ if(!p) return;
+ jsonParserFree(p->ctx);
+ free(p->lastkey);
+ free(p);
+}
+
+static jsonObject* _jsonParseStringImpl(const char* str, void (*errorHandler) (const char*) ) {
+ jsonInternalParser* parser = _jsonNewInternalParser();
+ parser->handleError = errorHandler;
+ jsonParseChunk( parser->ctx, str, strlen(str), JSON_PARSE_LAST_CHUNK );
+ jsonObject* obj = parser->obj;
+ _jsonInternalParserFree(parser);
+ return obj;
+}
+
+jsonObject* jsonParseStringHandleError(
+ void (*errorHandler) (const char*), char* str, ... ) {
+ if(!str) return NULL;
+ VA_LIST_TO_STRING(str);
+ return _jsonParseStringImpl(VA_BUF, errorHandler);
+}
+
+jsonObject* jsonParseString( const char* str ) {
+ if(!str) return NULL;
+ jsonObject* obj = _jsonParseStringImpl(str, NULL);
+ jsonObject* obj2 = jsonObjectDecodeClass(obj);
+ jsonObjectFree(obj);
+ return obj2;
+}
+
+jsonObject* jsonParseStringRaw( const char* str ) {
+ if(!str) return NULL;
+ return _jsonParseStringImpl(str, NULL);
+}
+
+jsonObject* jsonParseStringFmt( const char* str, ... ) {
+ if(!str) return NULL;
+ VA_LIST_TO_STRING(str);
+ return _jsonParseStringImpl(VA_BUF, NULL);
+}
+
+
+#define JSON_SHOVE_ITEM(ctx,type) \
+ jsonInternalParser* p = (jsonInternalParser*) ctx;\
+ _jsonInsertParserItem(p, jsonNewObjectType(type));
+
+void _jsonHandleStartObject(void* ctx) { JSON_SHOVE_ITEM(ctx, JSON_HASH); }
+void _jsonHandleStartArray(void* ctx) { JSON_SHOVE_ITEM(ctx, JSON_ARRAY); }
+void _jsonHandleNull(void* ctx) { JSON_SHOVE_ITEM(ctx, JSON_NULL); }
+
+void _jsonHandleObjectKey(void* ctx, char* key) {
+ jsonInternalParser* p = (jsonInternalParser*) ctx;
+ free(p->lastkey);
+ p->lastkey = strdup(key);
+}
+
+void _jsonHandleEndObject(void* ctx) {
+ jsonInternalParser* p = (jsonInternalParser*) ctx;
+ p->current = p->current->parent;
+}
+
+void _jsonHandleEndArray(void* ctx) {
+ jsonInternalParser* p = (jsonInternalParser*) ctx;
+ p->current = p->current->parent;
+}
+
+void _jsonHandleString(void* ctx, char* string) {
+ jsonInternalParser* p = (jsonInternalParser*) ctx;
+ _jsonInsertParserItem(p, jsonNewObject(string));
+}
+
+void _jsonHandleBool(void* ctx, int boolval) {
+ jsonInternalParser* p = (jsonInternalParser*) ctx;
+ jsonObject* obj = jsonNewObjectType(JSON_BOOL);
+ obj->value.b = boolval;
+ _jsonInsertParserItem(p, obj);
+}
+
+void _jsonHandleNumber(void* ctx, double num) {
+ jsonInternalParser* p = (jsonInternalParser*) ctx;
+ _jsonInsertParserItem(p, jsonNewNumberObject(num));
+}
+
+void _jsonHandleError(void* ctx, char* str, ...) {
+ jsonInternalParser* p = (jsonInternalParser*) ctx;
+ VA_LIST_TO_STRING(str);
+
+ if( p->handleError )
+ p->handleError(VA_BUF);
+ else
+ if( jsonClientErrorCallback )
+ jsonClientErrorCallback(VA_BUF);
+
+ else fprintf(stderr, "%s\n", VA_BUF);
+ jsonObjectFree(p->obj);
+ p->obj = NULL;
+}
+
+
+void _jsonInsertParserItem( jsonInternalParser* p, jsonObject* newo ) {
+
+ if( !p->obj ) {
+
+ /* new parser, set the new object to our object */
+ p->obj = p->current = newo;
+
+ } else {
+
+ /* insert the new object into the current container object */
+ switch(p->current->type) {
+ case JSON_HASH : jsonObjectSetKey(p->current, p->lastkey, newo); break;
+ case JSON_ARRAY: jsonObjectPush(p->current, newo); break;
+ default: fprintf(stderr, "%s:%d -> how?\n", JSON_LOG_MARK);
+ }
+
+ /* if the new object is a container object, make it our current container */
+ if( newo->type == JSON_ARRAY || newo->type == JSON_HASH )
+ p->current = newo;
+ }
+}
+
+
Copied: branches/autotools/src/libopensrf/osrf_json_test.c (from rev 1120, trunk/src/libopensrf/osrf_json_test.c)
===================================================================
--- branches/autotools/src/libopensrf/osrf_json_test.c (rev 0)
+++ branches/autotools/src/libopensrf/osrf_json_test.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,55 @@
+/*
+ * Basic JSON test module. Needs more strenous tests....
+ *
+ */
+#include <stdio.h>
+#include <opensrf/osrf_json.h>
+
+static void speedTest();
+
+
+int main(int argc, char* argv[]) {
+ /* XXX add support for command line test type specification */
+ speedTest();
+ return 0;
+}
+
+
+
+static void speedTest() {
+
+ /* creates a giant json object, generating JSON strings
+ * of subobjects as it goes. */
+
+ int i,k;
+ int count = 50;
+ char buf[16];
+ char* jsonString;
+
+ jsonObject* array;
+ jsonObject* dupe;
+ jsonObject* hash = jsonNewObject(NULL);
+
+ for(i = 0; i < count; i++) {
+
+ snprintf(buf, sizeof(buf), "key_%d", i);
+
+ array = jsonNewObject(NULL);
+ for(k = 0; k < count + i; k++) {
+ jsonObjectPush(array, jsonNewNumberObject(k));
+ jsonObjectPush(array, jsonNewObject(NULL));
+ jsonObjectPush(array, jsonNewObjectFmt("str %d-%d", i, k));
+ }
+ jsonObjectSetKey(hash, buf, array);
+
+ jsonString = jsonObjectToJSON(hash);
+ printf("%s\n\n", jsonString);
+ dupe = jsonParseString(jsonString);
+
+ jsonObjectFree(dupe);
+ free(jsonString);
+ }
+
+ jsonObjectFree(hash);
+}
+
Copied: branches/autotools/src/libopensrf/osrf_json_tools.c (from rev 1120, trunk/src/libopensrf/osrf_json_tools.c)
===================================================================
--- branches/autotools/src/libopensrf/osrf_json_tools.c (rev 0)
+++ branches/autotools/src/libopensrf/osrf_json_tools.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,297 @@
+/*
+Copyright (C) 2006 Georgia Public Library Service
+Bill Erickson <billserickson at gmail.com>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+*/
+
+#include <opensrf/osrf_json.h>
+
+jsonObject* _jsonObjectEncodeClass( const jsonObject* obj, int ignoreClass );
+
+
+jsonObject* jsonObjectFindPath( const jsonObject* obj, char* path, ...);
+jsonObject* _jsonObjectFindPathRecurse(const jsonObject* obj, char* root, char* path);
+jsonObject* __jsonObjectFindPathRecurse(const jsonObject* obj, char* root);
+
+
+static char* __tabs(int count) {
+ growing_buffer* buf = buffer_init(24);
+ int i;
+ for(i=0;i<count;i++) OSRF_BUFFER_ADD(buf, " ");
+ return buffer_release(buf);
+}
+
+char* jsonFormatString( const char* string ) {
+ if(!string) return strdup("");
+
+ growing_buffer* buf = buffer_init(64);
+ int i;
+ int depth = 0;
+ char* tab = NULL;
+
+ char c;
+ for(i=0; i!= strlen(string); i++) {
+ c = string[i];
+
+ if( c == '{' || c == '[' ) {
+
+ tab = __tabs(++depth);
+ buffer_fadd( buf, "%c\n%s", c, tab);
+ free(tab);
+
+ } else if( c == '}' || c == ']' ) {
+
+ tab = __tabs(--depth);
+ buffer_fadd( buf, "\n%s%c", tab, c);
+ free(tab);
+
+ if(string[i+1] != ',') {
+ tab = __tabs(depth);
+ buffer_fadd( buf, "%s", tab );
+ free(tab);
+ }
+
+ } else if( c == ',' ) {
+
+ tab = __tabs(depth);
+ buffer_fadd(buf, ",\n%s", tab);
+ free(tab);
+
+ } else { buffer_add_char(buf, c); }
+
+ }
+
+ return buffer_release(buf);
+}
+
+
+
+jsonObject* jsonObjectDecodeClass( const jsonObject* obj ) {
+ if(!obj) return jsonNewObject(NULL);
+
+ jsonObject* newObj = NULL;
+ const jsonObject* classObj = NULL;
+ const jsonObject* payloadObj = NULL;
+ int i;
+
+ if( obj->type == JSON_HASH ) {
+
+ /* are we a special class object? */
+ if( (classObj = jsonObjectGetKeyConst( obj, JSON_CLASS_KEY )) ) {
+
+ /* do we have a payload */
+ if( (payloadObj = jsonObjectGetKeyConst( obj, JSON_DATA_KEY )) ) {
+ newObj = jsonObjectDecodeClass( payloadObj );
+ jsonObjectSetClass( newObj, jsonObjectGetString(classObj) );
+
+ } else { /* class is defined but there is no payload */
+ return NULL;
+ }
+
+ } else { /* we're a regular hash */
+
+ jsonIterator* itr = jsonNewIterator(obj);
+ jsonObject* tmp;
+ newObj = jsonNewObjectType(JSON_HASH);
+ while( (tmp = jsonIteratorNext(itr)) ) {
+ jsonObject* o = jsonObjectDecodeClass(tmp);
+ jsonObjectSetKey( newObj, itr->key, o );
+ }
+ jsonIteratorFree(itr);
+ }
+
+ } else {
+
+ if( obj->type == JSON_ARRAY ) { /* we're an array */
+ newObj = jsonNewObjectType(JSON_ARRAY);
+ for( i = 0; i != obj->size; i++ ) {
+ jsonObject* tmp = jsonObjectDecodeClass(jsonObjectGetIndex( obj, i ) );
+ jsonObjectSetIndex( newObj, i, tmp );
+ }
+
+ } else { /* not an aggregate type */
+ newObj = jsonObjectClone(obj);
+ }
+ }
+
+ return newObj;
+}
+
+jsonObject* jsonObjectEncodeClass( const jsonObject* obj ) {
+ return _jsonObjectEncodeClass( obj, 0 );
+}
+
+jsonObject* _jsonObjectEncodeClass( const jsonObject* obj, int ignoreClass ) {
+
+ //if(!obj) return NULL;
+ if(!obj) return jsonNewObject(NULL);
+ jsonObject* newObj = NULL;
+
+ if( obj->classname && ! ignoreClass ) {
+ newObj = jsonNewObjectType(JSON_HASH);
+
+ jsonObjectSetKey( newObj,
+ JSON_CLASS_KEY, jsonNewObject(obj->classname) );
+
+ jsonObjectSetKey( newObj,
+ JSON_DATA_KEY, _jsonObjectEncodeClass(obj, 1));
+
+ } else if( obj->type == JSON_HASH ) {
+
+ jsonIterator* itr = jsonNewIterator(obj);
+ jsonObject* tmp;
+ newObj = jsonNewObjectType(JSON_HASH);
+
+ while( (tmp = jsonIteratorNext(itr)) ) {
+ jsonObjectSetKey( newObj, itr->key,
+ _jsonObjectEncodeClass(tmp, 0));
+ }
+ jsonIteratorFree(itr);
+
+ } else if( obj->type == JSON_ARRAY ) {
+
+ newObj = jsonNewObjectType(JSON_ARRAY);
+ int i;
+ for( i = 0; i != obj->size; i++ ) {
+ jsonObjectSetIndex( newObj, i,
+ _jsonObjectEncodeClass(jsonObjectGetIndex( obj, i ), 0 ));
+ }
+
+ } else {
+ newObj = jsonObjectClone(obj);
+ }
+
+ return newObj;
+}
+
+jsonObject* jsonParseFile( char* filename ) {
+ if(!filename) return NULL;
+ char* data = file_to_string(filename);
+ jsonObject* o = jsonParseString(data);
+ free(data);
+ return o;
+}
+
+
+
+jsonObject* jsonObjectFindPath( const jsonObject* obj, char* format, ...) {
+ if(!obj || !format || strlen(format) < 1) return NULL;
+
+ VA_LIST_TO_STRING(format);
+ char* buf = VA_BUF;
+ char* token = NULL;
+ char* t = buf;
+ char* tt; /* strtok storage */
+
+ /* copy the path before strtok_r destroys it */
+ char* pathcopy = strdup(buf);
+
+ /* grab the root of the path */
+ token = strtok_r(t, "/", &tt);
+ if(!token) return NULL;
+
+ /* special case where path starts with // (start anywhere) */
+ if(strlen(pathcopy) > 2 && pathcopy[0] == '/' && pathcopy[1] == '/') {
+ jsonObject* it = _jsonObjectFindPathRecurse(obj, token, pathcopy + 1);
+ free(pathcopy);
+ return it;
+ }
+
+ free(pathcopy);
+
+ t = NULL;
+ do {
+ obj = jsonObjectGetKey(obj, token);
+ } while( (token = strtok_r(NULL, "/", &tt)) && obj);
+
+ return jsonObjectClone(obj);
+}
+
+/* --------------------------------------------------------------- */
+
+
+
+jsonObject* _jsonObjectFindPathRecurse(const jsonObject* obj, char* root, char* path) {
+
+ if(!obj || ! root || !path) return NULL;
+
+ /* collect all of the potential objects */
+ jsonObject* arr = __jsonObjectFindPathRecurse(obj, root);
+
+ /* container for fully matching objects */
+ jsonObject* newarr = jsonParseString("[]");
+ int i;
+
+ /* path is just /root or /root/ */
+ if( strlen(root) + 2 >= strlen(path) ) {
+ return arr;
+
+ } else {
+
+ /* gather all of the sub-objects that match the full path */
+ for( i = 0; i < arr->size; i++ ) {
+ const jsonObject* a = jsonObjectGetIndex(arr, i);
+ jsonObject* thing = jsonObjectFindPath(a , path + strlen(root) + 1);
+
+ if(thing) { //jsonObjectPush(newarr, thing);
+ if(thing->type == JSON_ARRAY) {
+ int i;
+ for( i = 0; i != thing->size; i++ )
+ jsonObjectPush(newarr, jsonObjectClone(jsonObjectGetIndex(thing,i)));
+ jsonObjectFree(thing);
+
+ } else {
+ jsonObjectPush(newarr, thing);
+ }
+ }
+ }
+ }
+
+ jsonObjectFree(arr);
+ return newarr;
+}
+
+jsonObject* __jsonObjectFindPathRecurse(const jsonObject* obj, char* root) {
+
+ jsonObject* arr = jsonParseString("[]");
+ if(!obj) return arr;
+
+ int i;
+
+ /* if the current object has a node that matches, add it */
+
+ jsonObject* o = jsonObjectGetKey(obj, root);
+ if(o) jsonObjectPush( arr, jsonObjectClone(o) );
+
+ jsonObject* tmp = NULL;
+ jsonObject* childarr;
+ jsonIterator* itr = jsonNewIterator(obj);
+
+ /* recurse through the children and find all potential nodes */
+ while( (tmp = jsonIteratorNext(itr)) ) {
+ childarr = __jsonObjectFindPathRecurse(tmp, root);
+ if(childarr && childarr->size > 0) {
+ for( i = 0; i!= childarr->size; i++ ) {
+ jsonObjectPush( arr, jsonObjectClone(jsonObjectGetIndex(childarr, i)) );
+ }
+ }
+ jsonObjectFree(childarr);
+ }
+
+ jsonIteratorFree(itr);
+
+ return arr;
+}
+
+
+
+
Copied: branches/autotools/src/libopensrf/osrf_json_xml.c (from rev 1120, trunk/src/libopensrf/osrf_json_xml.c)
===================================================================
--- branches/autotools/src/libopensrf/osrf_json_xml.c (rev 0)
+++ branches/autotools/src/libopensrf/osrf_json_xml.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,365 @@
+#include <opensrf/osrf_json_xml.h>
+
+#ifdef OSRF_JSON_ENABLE_XML_UTILS
+
+struct osrfXMLGatewayParserStruct {
+ osrfList* objStack;
+ osrfList* keyStack;
+ jsonObject* obj;
+ short inString;
+ short inNumber;
+ short error;
+};
+typedef struct osrfXMLGatewayParserStruct osrfXMLGatewayParser;
+
+/** returns the attribute value with the given attribute name */
+static char* getXMLAttr(const xmlChar** atts, char* attr_name) {
+ int i;
+ if (atts != NULL) {
+ for(i = 0; (atts[i] != NULL); i++) {
+ if(strcmp((char*) atts[i++], attr_name) == 0) {
+ if(atts[i] != NULL)
+ return (char*) atts[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+
+static void appendChild(osrfXMLGatewayParser* p, jsonObject* obj) {
+
+ if(p->obj == NULL)
+ p->obj = obj;
+
+ if(p->objStack->size == 0)
+ return;
+
+ jsonObject* parent = OSRF_LIST_GET_INDEX(p->objStack, p->objStack->size - 1);
+
+ if(parent->type == JSON_ARRAY) {
+ jsonObjectPush(parent, obj);
+ } else {
+ char* key = osrfListPop(p->keyStack);
+ jsonObjectSetKey(parent, key, obj);
+ free(key); /* the list is not setup for auto-freeing */
+ }
+}
+
+
+
+static void startElementHandler(
+ void *parser, const xmlChar *name, const xmlChar **atts) {
+
+ osrfXMLGatewayParser* p = (osrfXMLGatewayParser*) parser;
+ jsonObject* obj;
+
+ char* hint = getXMLAttr(atts, "class_hint");
+
+ if(!strcmp((char*) name, "null")) {
+ appendChild(p, jsonNewObject(NULL));
+ return;
+ }
+
+ if(!strcmp((char*) name, "string")) {
+ p->inString = 1;
+ return;
+ }
+
+ if(!strcmp((char*) name, "element")) {
+ osrfListPush(p->keyStack, strdup(getXMLAttr(atts, "key")));
+ return;
+ }
+
+ if(!strcmp((char*) name, "object")) {
+ obj = jsonNewObject(NULL);
+ jsonObjectSetClass(obj, hint); /* OK if hint is NULL */
+ obj->type = JSON_HASH;
+ appendChild(p, obj);
+ osrfListPush(p->objStack, obj);
+ return;
+ }
+
+ if(!strcmp((char*) name, "array")) {
+ obj = jsonNewObject(NULL);
+ jsonObjectSetClass(obj, hint); /* OK if hint is NULL */
+ obj->type = JSON_ARRAY;
+ appendChild(p, obj);
+ osrfListPush(p->objStack, obj);
+ return;
+ }
+
+
+ if(!strcmp((char*) name, "number")) {
+ p->inNumber = 1;
+ return;
+ }
+
+ if(!strcmp((char*) name, "boolean")) {
+ obj = jsonNewObject(NULL);
+ obj->type = JSON_BOOL;
+ char* val = getXMLAttr(atts, "value");
+ if(val && !strcmp(val, "true"))
+ obj->value.b = 1;
+
+ return;
+ }
+}
+
+static void endElementHandler( void *parser, const xmlChar *name) {
+ if(!strcmp((char*) name, "array") || !strcmp((char*) name, "object")) {
+ osrfXMLGatewayParser* p = (osrfXMLGatewayParser*) parser;
+ osrfListPop(p->objStack);
+ }
+}
+
+static void characterHandler(void *parser, const xmlChar *ch, int len) {
+
+ char data[len+1];
+ strncpy(data, (char*) ch, len);
+ data[len] = '\0';
+ osrfXMLGatewayParser* p = (osrfXMLGatewayParser*) parser;
+
+ if(p->inString) {
+ appendChild(p, jsonNewObject(data));
+ p->inString = 0;
+ return;
+ }
+
+ if(p->inNumber) {
+ appendChild(p, jsonNewNumberObject(atof(data)));
+ p->inNumber = 0;
+ return;
+ }
+}
+
+static void parseWarningHandler(void *parser, const char* msg, ...) {
+ VA_LIST_TO_STRING(msg);
+ fprintf(stderr, "Parser warning %s\n", VA_BUF);
+ fflush(stderr);
+}
+
+static void parseErrorHandler(void *parser, const char* msg, ...) {
+
+ VA_LIST_TO_STRING(msg);
+ fprintf(stderr, "Parser error %s\n", VA_BUF);
+ fflush(stderr);
+
+ osrfXMLGatewayParser* p = (osrfXMLGatewayParser*) parser;
+
+ /* keyStack as strdup'ed strings. The list may
+ * not be empty, so tell it to free the items
+ * when it's freed (from the main routine)
+ */
+ osrfListSetDefaultFree(p->keyStack);
+ jsonObjectFree(p->obj);
+
+ p->obj = NULL;
+ p->error = 1;
+}
+
+
+
+
+static xmlSAXHandler SAXHandlerStruct = {
+ NULL, /* internalSubset */
+ NULL, /* isStandalone */
+ NULL, /* hasInternalSubset */
+ NULL, /* hasExternalSubset */
+ NULL, /* resolveEntity */
+ NULL, /* getEntity */
+ NULL, /* entityDecl */
+ NULL, /* notationDecl */
+ NULL, /* attributeDecl */
+ NULL, /* elementDecl */
+ NULL, /* unparsedEntityDecl */
+ NULL, /* setDocumentLocator */
+ NULL, /* startDocument */
+ NULL, /* endDocument */
+ startElementHandler, /* startElement */
+ endElementHandler, /* endElement */
+ NULL, /* reference */
+ characterHandler, /* characters */
+ NULL, /* ignorableWhitespace */
+ NULL, /* processingInstruction */
+ NULL, /* comment */
+ parseWarningHandler, /* xmlParserWarning */
+ parseErrorHandler, /* xmlParserError */
+ NULL, /* xmlParserFatalError : unused */
+ NULL, /* getParameterEntity */
+ NULL, /* cdataBlock; */
+ NULL, /* externalSubset; */
+ 1,
+ NULL,
+ NULL, /* startElementNs */
+ NULL, /* endElementNs */
+ NULL /* xmlStructuredErrorFunc */
+};
+
+static const xmlSAXHandlerPtr SAXHandler = &SAXHandlerStruct;
+
+jsonObject* jsonXMLToJSONObject(const char* xml) {
+
+ osrfXMLGatewayParser parser;
+
+ /* don't define freeItem, since objects will be cleaned by freeing the parent */
+ parser.objStack = osrfNewList();
+ /* don't define freeItem, since the list eill end up empty if there are no errors*/
+ parser.keyStack = osrfNewList();
+ parser.obj = NULL;
+ parser.inString = 0;
+ parser.inNumber = 0;
+
+ xmlParserCtxtPtr ctxt = xmlCreatePushParserCtxt(SAXHandler, &parser, "", 0, NULL);
+ xmlParseChunk(ctxt, xml, strlen(xml), 1);
+
+ osrfListFree(parser.objStack);
+ osrfListFree(parser.keyStack);
+ xmlFreeParserCtxt(ctxt);
+ xmlCleanupCharEncodingHandlers();
+ xmlDictCleanup();
+ xmlCleanupParser();
+
+ return parser.obj;
+}
+
+
+
+
+
+
+static char* _escape_xml (char*);
+static int _recurse_jsonObjectToXML(jsonObject*, growing_buffer*);
+
+char* jsonObjectToXML(jsonObject* obj) {
+
+ growing_buffer * res_xml;
+ char * output;
+
+ res_xml = buffer_init(1024);
+
+ if (!obj)
+ return strdup("<null/>");
+
+ _recurse_jsonObjectToXML( obj, res_xml );
+ output = buffer_data(res_xml);
+
+ buffer_free(res_xml);
+
+ return output;
+
+}
+
+int _recurse_jsonObjectToXML(jsonObject* obj, growing_buffer* res_xml) {
+
+ char * hint = NULL;
+ char * bool_val = NULL;
+ int i = 0;
+
+ if (obj->classname)
+ hint = strdup(obj->classname);
+
+ if(obj->type == JSON_NULL) {
+
+ if (hint)
+ buffer_fadd(res_xml, "<null class_hint=\"%s\"/>",hint);
+ else
+ buffer_add(res_xml, "<null/>");
+
+ } else if(obj->type == JSON_BOOL) {
+
+ if (obj->value.b)
+ bool_val = strdup("true");
+ else
+ bool_val = strdup("false");
+
+ if (hint)
+ buffer_fadd(res_xml, "<boolean value=\"%s\" class_hint=\"%s\"/>", bool_val, hint);
+ else
+ buffer_fadd(res_xml, "<boolean value=\"%s\"/>", bool_val);
+
+ free(bool_val);
+
+ } else if (obj->type == JSON_STRING) {
+ if (hint) {
+ char * t = _escape_xml(jsonObjectGetString(obj));
+ buffer_fadd(res_xml,"<string class_hint=\"%s\">%s</string>", hint, t);
+ free(t);
+ } else {
+ char * t = _escape_xml(jsonObjectGetString(obj));
+ buffer_fadd(res_xml,"<string>%s</string>", t);
+ free(t);
+ }
+
+ } else if(obj->type == JSON_NUMBER) {
+ double x = jsonObjectGetNumber(obj);
+ if (hint) {
+ if (x == (int)x)
+ buffer_fadd(res_xml,"<number class_hint=\"%s\">%d</number>", hint, (int)x);
+ else
+ buffer_fadd(res_xml,"<number class_hint=\"%s\">%lf</number>", hint, x);
+ } else {
+ if (x == (int)x)
+ buffer_fadd(res_xml,"<number>%d</number>", (int)x);
+ else
+ buffer_fadd(res_xml,"<number>%lf</number>", x);
+ }
+
+ } else if (obj->type == JSON_ARRAY) {
+
+ if (hint)
+ buffer_fadd(res_xml,"<array class_hint=\"%s\">", hint);
+ else
+ buffer_add(res_xml,"<array>");
+
+ for ( i = 0; i!= obj->size; i++ )
+ _recurse_jsonObjectToXML(jsonObjectGetIndex(obj,i), res_xml);
+
+ buffer_add(res_xml,"</array>");
+
+ } else if (obj->type == JSON_HASH) {
+
+ if (hint)
+ buffer_fadd(res_xml,"<object class_hint=\"%s\">", hint);
+ else
+ buffer_add(res_xml,"<object>");
+
+ jsonIterator* itr = jsonNewIterator(obj);
+ jsonObject* tmp;
+ while( (tmp = jsonIteratorNext(itr)) ) {
+ buffer_fadd(res_xml,"<element key=\"%s\">",itr->key);
+ _recurse_jsonObjectToXML(tmp, res_xml);
+ buffer_add(res_xml,"</element>");
+ }
+ jsonIteratorFree(itr);
+
+ buffer_add(res_xml,"</object>");
+ }
+
+ if (hint)
+ free(hint);
+
+ return 1;
+}
+
+char* _escape_xml (char* text) {
+ char* out;
+ growing_buffer* b = buffer_init(256);
+ int len = strlen(text);
+ int i;
+ for (i = 0; i < len; i++) {
+ if (text[i] == '&')
+ buffer_add(b,"&");
+ else if (text[i] == '<')
+ buffer_add(b,"<");
+ else if (text[i] == '>')
+ buffer_add(b,">");
+ else
+ buffer_add_char(b,text[i]);
+ }
+ out = buffer_data(b);
+ buffer_free(b);
+ return out;
+}
+
+#endif
Copied: branches/autotools/src/libopensrf/osrf_legacy_json.c (from rev 1120, trunk/src/libopensrf/osrf_legacy_json.c)
===================================================================
--- branches/autotools/src/libopensrf/osrf_legacy_json.c (rev 0)
+++ branches/autotools/src/libopensrf/osrf_legacy_json.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -0,0 +1,881 @@
+/*
+Copyright (C) 2006 Georgia Public Library Service
+Bill Erickson <billserickson at gmail.com>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+*/
+
+
+#include <opensrf/osrf_legacy_json.h>
+
+/* keep a copy of the length of the current json string so we don't
+ * have to calculate it in each function
+ */
+int current_strlen;
+
+
+jsonObject* legacy_jsonParseString( const char* string) {
+ return json_parse_string( (char*) string );
+}
+
+jsonObject* legacy_jsonParseStringFmt( const char* string, ... ) {
+ VA_LIST_TO_STRING(string);
+ return json_parse_string( VA_BUF );
+}
+
+
+jsonObject* json_parse_string(char* string) {
+
+ if(string == NULL) return NULL;
+
+ current_strlen = strlen(string);
+
+ if(current_strlen == 0)
+ return NULL;
+
+ unsigned long index = 0;
+
+ json_eat_ws(string, &index, 1, current_strlen); /* remove leading whitespace */
+ if(index == current_strlen) return NULL;
+
+ jsonObject* obj = jsonNewObject(NULL);
+
+ int status = _json_parse_string(string, &index, obj, current_strlen);
+ if(!status) return obj;
+
+ if(status == -2) {
+ jsonObjectFree(obj);
+ return NULL;
+ }
+
+ return NULL;
+}
+
+
+int _json_parse_string(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
+ if( !string || !index || *index >= current_strlen) return -2;
+
+ int status = 0; /* return code from parsing routines */
+ char* classname = NULL; /* object class hint */
+ json_eat_ws(string, index, 1, current_strlen); /* remove leading whitespace */
+
+ char c = string[*index];
+
+ /* remove any leading comments */
+ if( c == '/' ) {
+
+ while(1) {
+ (*index)++; /* move to second comment char */
+ status = json_eat_comment(string, index, &classname, 1, current_strlen);
+ if(status) return status;
+
+ json_eat_ws(string, index, 1, current_strlen);
+ c = string[*index];
+ if(c != '/')
+ break;
+ }
+ }
+
+ json_eat_ws(string, index, 1, current_strlen); /* remove leading whitespace */
+
+ if(*index >= current_strlen)
+ return -2;
+
+ switch(c) {
+
+ /* json string */
+ case '"':
+ (*index)++;
+ status = json_parse_json_string(string, index, obj, current_strlen);
+ break;
+
+ /* json array */
+ case '[':
+ (*index)++;
+ status = json_parse_json_array(string, index, obj, current_strlen);
+ break;
+
+ /* json object */
+ case '{':
+ (*index)++;
+ status = json_parse_json_object(string, index, obj, current_strlen);
+ break;
+
+ /* NULL */
+ case 'n':
+ case 'N':
+ status = json_parse_json_null(string, index, obj, current_strlen);
+ break;
+
+
+ /* true, false */
+ case 'f':
+ case 'F':
+ case 't':
+ case 'T':
+ status = json_parse_json_bool(string, index, obj, current_strlen);
+ break;
+
+ default:
+ if(isdigit(c) || c == '.' || c == '-') { /* are we a number? */
+ status = json_parse_json_number(string, index, obj, current_strlen);
+ if(status) return status;
+ break;
+ }
+
+ (*index)--;
+ /* we should never get here */
+ return json_handle_error(string, index, "_json_parse_string() final switch clause");
+ }
+
+ if(status) return status;
+
+ json_eat_ws(string, index, 1, current_strlen);
+
+ if( *index < current_strlen ) {
+ /* remove any trailing comments */
+ c = string[*index];
+ if( c == '/' ) {
+ (*index)++;
+ status = json_eat_comment(string, index, NULL, 0, current_strlen);
+ if(status) return status;
+ }
+ }
+
+ if(classname){
+ jsonObjectSetClass(obj, classname);
+ free(classname);
+ }
+
+ return 0;
+}
+
+
+int json_parse_json_null(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
+
+ if(*index >= (current_strlen - 3)) {
+ return json_handle_error(string, index,
+ "_parse_json_null(): invalid null" );
+ }
+
+ if(!strncasecmp(string + (*index), "null", 4)) {
+ (*index) += 4;
+ obj->type = JSON_NULL;
+ return 0;
+ } else {
+ return json_handle_error(string, index,
+ "_parse_json_null(): invalid null" );
+ }
+}
+
+/* should be at the first character of the bool at this point */
+int json_parse_json_bool(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
+ if( ! string || ! obj || *index >= current_strlen ) return -1;
+
+ char* ret = "json_parse_json_bool(): truncated bool";
+
+ if( *index >= (current_strlen - 5))
+ return json_handle_error(string, index, ret);
+
+ if(!strncasecmp( string + (*index), "false", 5)) {
+ (*index) += 5;
+ obj->value.b = 0;
+ obj->type = JSON_BOOL;
+ return 0;
+ }
+
+ if( *index >= (current_strlen - 4))
+ return json_handle_error(string, index, ret);
+
+ if(!strncasecmp( string + (*index), "true", 4)) {
+ (*index) += 4;
+ obj->value.b = 1;
+ obj->type = JSON_BOOL;
+ return 0;
+ }
+
+ return json_handle_error(string, index, ret);
+}
+
+
+/* expecting the first character of the number */
+int json_parse_json_number(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
+ if( ! string || ! obj || *index >= current_strlen ) return -1;
+
+ growing_buffer* buf = buffer_init(64);
+ char c = string[*index];
+
+ int done = 0;
+ int dot_seen = 0;
+
+ /* negative number? */
+ if(c == '-') { buffer_add(buf, "-"); (*index)++; }
+
+ c = string[*index];
+
+ while(*index < current_strlen) {
+
+ if(isdigit(c)) {
+ buffer_add_char(buf, c);
+ }
+
+ else if( c == '.' ) {
+ if(dot_seen) {
+ buffer_free(buf);
+ return json_handle_error(string, index,
+ "json_parse_json_number(): malformed json number");
+ }
+ dot_seen = 1;
+ buffer_add_char(buf, c);
+ } else {
+ done = 1; break;
+ }
+
+ (*index)++;
+ c = string[*index];
+ if(done) break;
+ }
+
+ obj->type = JSON_NUMBER;
+ obj->value.n = strtod(buf->buf, NULL);
+ buffer_free(buf);
+ return 0;
+}
+
+/* index should point to the character directly following the '['. when done
+ * index will point to the character directly following the ']' character
+ */
+int json_parse_json_array(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
+
+ if( ! string || ! obj || ! index || *index >= current_strlen ) return -1;
+
+ int status = 0;
+ int in_parse = 0; /* true if this array already contains one item */
+ obj->type = JSON_ARRAY;
+ int set = 0;
+ int done = 0;
+
+ while(*index < current_strlen) {
+
+ json_eat_ws(string, index, 1, current_strlen);
+
+ if(string[*index] == ']') {
+ (*index)++;
+ done = 1;
+ break;
+ }
+
+ if(in_parse) {
+ json_eat_ws(string, index, 1, current_strlen);
+ if(string[*index] != ',') {
+ return json_handle_error(string, index,
+ "json_parse_json_array(): array item not followed by a ','");
+ }
+ (*index)++;
+ json_eat_ws(string, index, 1, current_strlen);
+ }
+
+ jsonObject* item = jsonNewObject(NULL);
+
+ #ifndef STRICT_JSON_READ
+ if(*index < current_strlen) {
+ if(string[*index] == ',' || string[*index] == ']') {
+ status = 0;
+ set = 1;
+ }
+ }
+ if(!set) status = _json_parse_string(string, index, item, current_strlen);
+
+ #else
+ status = _json_parse_string(string, index, item, current_strlen);
+ #endif
+
+ if(status) { jsonObjectFree(item); return status; }
+ jsonObjectPush(obj, item);
+ in_parse = 1;
+ set = 0;
+ }
+
+ if(!done)
+ return json_handle_error(string, index,
+ "json_parse_json_array(): array not closed");
+
+ return 0;
+}
+
+
+/* index should point to the character directly following the '{'. when done
+ * index will point to the character directly following the '}'
+ */
+int json_parse_json_object(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
+ if( ! string || !obj || ! index || *index >= current_strlen ) return -1;
+
+ obj->type = JSON_HASH;
+ int status;
+ int in_parse = 0; /* true if we've already added one item to this object */
+ int set = 0;
+ int done = 0;
+
+ while(*index < current_strlen) {
+
+ json_eat_ws(string, index, 1, current_strlen);
+
+ if(string[*index] == '}') {
+ (*index)++;
+ done = 1;
+ break;
+ }
+
+ if(in_parse) {
+ if(string[*index] != ',') {
+ return json_handle_error(string, index,
+ "json_parse_json_object(): object missing ',' between elements" );
+ }
+ (*index)++;
+ json_eat_ws(string, index, 1, current_strlen);
+ }
+
+ /* first we grab the hash key */
+ jsonObject* key_obj = jsonNewObject(NULL);
+ status = _json_parse_string(string, index, key_obj, current_strlen);
+ if(status) return status;
+
+ if(key_obj->type != JSON_STRING) {
+ return json_handle_error(string, index,
+ "_json_parse_json_object(): hash key not a string");
+ }
+
+ char* key = key_obj->value.s;
+
+ json_eat_ws(string, index, 1, current_strlen);
+
+ if(string[*index] != ':') {
+ return json_handle_error(string, index,
+ "json_parse_json_object(): hash key not followed by ':' character");
+ }
+
+ (*index)++;
+
+ /* now grab the value object */
+ json_eat_ws(string, index, 1, current_strlen);
+ jsonObject* value_obj = jsonNewObject(NULL);
+
+#ifndef STRICT_JSON_READ
+ if(*index < current_strlen) {
+ if(string[*index] == ',' || string[*index] == '}') {
+ status = 0;
+ set = 1;
+ }
+ }
+ if(!set)
+ status = _json_parse_string(string, index, value_obj, current_strlen);
+
+#else
+ status = _json_parse_string(string, index, value_obj, current_strlen);
+#endif
+
+ if(status) return status;
+
+ /* put the data into the object and continue */
+ jsonObjectSetKey(obj, key, value_obj);
+ jsonObjectFree(key_obj);
+ in_parse = 1;
+ set = 0;
+ }
+
+ if(!done)
+ return json_handle_error(string, index,
+ "json_parse_json_object(): object not closed");
+
+ return 0;
+}
+
+
+
+/* when done, index will point to the character after the closing quote */
+int json_parse_json_string(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
+ if( ! string || ! index || *index >= current_strlen ) return -1;
+
+ int in_escape = 0;
+ int done = 0;
+ growing_buffer* buf = buffer_init(64);
+
+ while(*index < current_strlen) {
+
+ char c = string[*index];
+
+ switch(c) {
+
+ case '\\':
+ if(in_escape) {
+ buffer_add(buf, "\\");
+ in_escape = 0;
+ } else
+ in_escape = 1;
+ break;
+
+ case '"':
+ if(in_escape) {
+ buffer_add(buf, "\"");
+ in_escape = 0;
+ } else
+ done = 1;
+ break;
+
+ case 't':
+ if(in_escape) {
+ buffer_add(buf,"\t");
+ in_escape = 0;
+ } else
+ buffer_add_char(buf, c);
+ break;
+
+ case 'b':
+ if(in_escape) {
+ buffer_add(buf,"\b");
+ in_escape = 0;
+ } else
+ buffer_add_char(buf, c);
+ break;
+
+ case 'f':
+ if(in_escape) {
+ buffer_add(buf,"\f");
+ in_escape = 0;
+ } else
+ buffer_add_char(buf, c);
+ break;
+
+ case 'r':
+ if(in_escape) {
+ buffer_add(buf,"\r");
+ in_escape = 0;
+ } else
+ buffer_add_char(buf, c);
+ break;
+
+ case 'n':
+ if(in_escape) {
+ buffer_add(buf,"\n");
+ in_escape = 0;
+ } else
+ buffer_add_char(buf, c);
+ break;
+
+ case 'u':
+ if(in_escape) {
+ (*index)++;
+
+ if(*index >= (current_strlen - 4)) {
+ buffer_free(buf);
+ return json_handle_error(string, index,
+ "json_parse_json_string(): truncated escaped unicode"); }
+
+ char buff[5];
+ osrf_clearbuf(buff, sizeof(buff));
+ memcpy(buff, string + (*index), 4);
+
+
+ /* ----------------------------------------------------------------------- */
+ /* ----------------------------------------------------------------------- */
+ /* The following chunk was borrowed with permission from
+ json-c http://oss.metaparadigm.com/json-c/ */
+ unsigned char utf_out[3];
+ memset(utf_out, 0, sizeof(utf_out));
+
+ #define hexdigit(x) ( ((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
+
+ unsigned int ucs_char =
+ (hexdigit(string[*index] ) << 12) +
+ (hexdigit(string[*index + 1]) << 8) +
+ (hexdigit(string[*index + 2]) << 4) +
+ hexdigit(string[*index + 3]);
+
+ if (ucs_char < 0x80) {
+ utf_out[0] = ucs_char;
+ buffer_add(buf, (char*) utf_out);
+
+ } else if (ucs_char < 0x800) {
+ utf_out[0] = 0xc0 | (ucs_char >> 6);
+ utf_out[1] = 0x80 | (ucs_char & 0x3f);
+ buffer_add(buf, (char*) utf_out);
+
+ } else {
+ utf_out[0] = 0xe0 | (ucs_char >> 12);
+ utf_out[1] = 0x80 | ((ucs_char >> 6) & 0x3f);
+ utf_out[2] = 0x80 | (ucs_char & 0x3f);
+ buffer_add(buf, (char*) utf_out);
+ }
+ /* ----------------------------------------------------------------------- */
+ /* ----------------------------------------------------------------------- */
+
+ (*index) += 3;
+ in_escape = 0;
+
+ } else {
+
+ buffer_add_char(buf, c);
+ }
+
+ break;
+
+ default:
+ buffer_add_char(buf, c);
+ }
+
+ (*index)++;
+ if(done) break;
+ }
+
+ jsonObjectSetString(obj, buf->buf);
+ buffer_free(buf);
+ return 0;
+}
+
+
+void json_eat_ws(char* string, unsigned long* index, int eat_all, int current_strlen) {
+ if( ! string || ! index ) return;
+ if(*index >= current_strlen)
+ return;
+
+ if( eat_all ) { /* removes newlines, etc */
+ while(string[*index] == ' ' ||
+ string[*index] == '\n' ||
+ string[*index] == '\t')
+ (*index)++;
+ }
+
+ else
+ while(string[*index] == ' ') (*index)++;
+}
+
+
+/* index should be at the '*' character at the beginning of the comment.
+ * when done, index will point to the first character after the final /
+ */
+int json_eat_comment(char* string, unsigned long* index, char** buffer, int parse_class, int current_strlen) {
+ if( ! string || ! index || *index >= current_strlen ) return -1;
+
+
+ if(string[*index] != '*' && string[*index] != '/' )
+ return json_handle_error(string, index,
+ "json_eat_comment(): invalid character after /");
+
+ /* chop out any // style comments */
+ if(string[*index] == '/') {
+ (*index)++;
+ char c = string[*index];
+ while(*index < current_strlen) {
+ (*index)++;
+ if(c == '\n')
+ return 0;
+ c = string[*index];
+ }
+ return 0;
+ }
+
+ (*index)++;
+
+ int on_star = 0; /* true if we just saw a '*' character */
+
+ /* we're just past the '*' */
+ if(!parse_class) { /* we're not concerned with class hints */
+ while(*index < current_strlen) {
+ if(string[*index] == '/') {
+ if(on_star) {
+ (*index)++;
+ return 0;
+ }
+ }
+
+ if(string[*index] == '*') on_star = 1;
+ else on_star = 0;
+
+ (*index)++;
+ }
+ return 0;
+ }
+
+
+
+ growing_buffer* buf = buffer_init(64);
+
+ int first_dash = 0;
+ int second_dash = 0;
+ int third_dash = 0;
+ int fourth_dash = 0;
+
+ int in_hint = 0;
+ int done = 0;
+
+ /*--S hint--*/ /* <-- Hints look like this */
+ /*--E hint--*/
+
+ while(*index < current_strlen) {
+ char c = string[*index];
+
+ switch(c) {
+
+ case '-':
+ on_star = 0;
+ if(third_dash) fourth_dash = 1;
+ else if(in_hint) third_dash = 1;
+ else if(first_dash) second_dash = 1;
+ else first_dash = 1;
+ break;
+
+ case 'S':
+ on_star = 0;
+ if(second_dash && !in_hint) {
+ (*index)++;
+ json_eat_ws(string, index, 1, current_strlen);
+ (*index)--; /* this will get incremented at the bottom of the loop */
+ in_hint = 1;
+ break;
+ }
+
+ if(second_dash && in_hint) {
+ buffer_add_char(buf, c);
+ break;
+ }
+
+ case 'E':
+ on_star = 0;
+ if(second_dash && !in_hint) {
+ (*index)++;
+ json_eat_ws(string, index, 1, current_strlen);
+ (*index)--; /* this will get incremented at the bottom of the loop */
+ in_hint = 1;
+ break;
+ }
+
+ if(second_dash && in_hint) {
+ buffer_add_char(buf, c);
+ break;
+ }
+
+ case '*':
+ on_star = 1;
+ break;
+
+ case '/':
+ if(on_star)
+ done = 1;
+ else
+ on_star = 0;
+ break;
+
+ default:
+ on_star = 0;
+ if(in_hint)
+ buffer_add_char(buf, c);
+ }
+
+ (*index)++;
+ if(done) break;
+ }
+
+ if( buf->n_used > 0 && buffer)
+ *buffer = buffer_data(buf);
+
+ buffer_free(buf);
+ return 0;
+}
+
+int json_handle_error(char* string, unsigned long* index, char* err_msg) {
+
+ char buf[60];
+ osrf_clearbuf(buf, sizeof(buf));
+
+ if(*index > 30)
+ strncpy( buf, string + (*index - 30), 59 );
+ else
+ strncpy( buf, string, 59 );
+
+ fprintf(stderr,
+ "\nError parsing json string at charracter %c "
+ "(code %d) and index %ld\nString length: %d\nMsg:\t%s\nNear:\t%s\nFull String:\t%s\n",
+ string[*index], string[*index], *index, current_strlen, err_msg, buf, string );
+
+ return -1;
+}
+
+
+jsonObject* legacy_jsonParseFile( const char* filename ) {
+ return json_parse_file( filename );
+}
+
+jsonObject* json_parse_file(const char* filename) {
+ if(!filename) return NULL;
+ char* data = file_to_string(filename);
+ jsonObject* o = json_parse_string(data);
+ free(data);
+ return o;
+}
+
+
+
+char* legacy_jsonObjectToJSON( const jsonObject* obj ) {
+
+ if(obj == NULL) return strdup("null");
+
+ growing_buffer* buf = buffer_init(64);
+
+ /* add class hints if we have a class name */
+ if(obj->classname) {
+ buffer_add(buf,"/*--S ");
+ buffer_add(buf,obj->classname);
+ buffer_add(buf, "--*/");
+ }
+
+ switch( obj->type ) {
+
+ case JSON_BOOL:
+ if(obj->value.b) buffer_add(buf, "true");
+ else buffer_add(buf, "false");
+ break;
+
+ case JSON_NUMBER: {
+ double x = obj->value.n;
+
+ /* if the number does not need to be a double,
+ turn it into an int on the way out */
+ if( x == (int) x ) {
+ INT_TO_STRING((int)x);
+ buffer_add(buf, INTSTR);
+
+ } else {
+ DOUBLE_TO_STRING(x);
+ buffer_add(buf, DOUBLESTR);
+ }
+ break;
+ }
+
+ case JSON_NULL:
+ buffer_add(buf, "null");
+ break;
+
+ case JSON_STRING:
+ buffer_add(buf, "\"");
+ char* data = obj->value.s;
+ int len = strlen(data);
+
+ char* output = uescape(data, len, 1);
+ buffer_add(buf, output);
+ free(output);
+ buffer_add(buf, "\"");
+ break;
+
+ case JSON_ARRAY:
+ buffer_add(buf, "[");
+ int i;
+ for( i = 0; i!= obj->size; i++ ) {
+ const jsonObject* x = jsonObjectGetIndex(obj,i);
+ char* data = legacy_jsonObjectToJSON(x);
+ buffer_add(buf, data);
+ free(data);
+ if(i != obj->size - 1)
+ buffer_add(buf, ",");
+ }
+ buffer_add(buf, "]");
+ break;
+
+ case JSON_HASH:
+
+ buffer_add(buf, "{");
+ jsonIterator* itr = jsonNewIterator(obj);
+ jsonObject* tmp;
+
+ while( (tmp = jsonIteratorNext(itr)) ) {
+
+ buffer_add(buf, "\"");
+
+ char* key = itr->key;
+ int len = strlen(key);
+ char* output = uescape(key, len, 1);
+ buffer_add(buf, output);
+ free(output);
+
+ buffer_add(buf, "\":");
+ char* data = legacy_jsonObjectToJSON(tmp);
+ buffer_add(buf, data);
+ if(jsonIteratorHasNext(itr))
+ buffer_add(buf, ",");
+ free(data);
+ }
+
+ jsonIteratorFree(itr);
+ buffer_add(buf, "}");
+ break;
+
+ default:
+ fprintf(stderr, "Unknown object type %d\n", obj->type);
+ break;
+
+ }
+
+ /* close out the object hint */
+ if(obj->classname) {
+ buffer_add(buf, "/*--E ");
+ buffer_add(buf, obj->classname);
+ buffer_add(buf, "--*/");
+ }
+
+ char* data = buffer_data(buf);
+ buffer_free(buf);
+ return data;
+}
+
+
+
+static jsonObjectNode* makeNode(jsonObject* obj, unsigned long index, char* key) {
+ jsonObjectNode* node = safe_malloc(sizeof(jsonObjectNode));
+ node->item = obj;
+ node->index = index;
+ node->key = key;
+ return node;
+}
+
+jsonObjectIterator* jsonNewObjectIterator(const jsonObject* obj) {
+ if(!obj) return NULL;
+ jsonObjectIterator* itr = safe_malloc(sizeof(jsonObjectIterator));
+ itr->iterator = jsonNewIterator(obj);
+ itr->obj = obj;
+ itr->done = 0;
+ itr->current = NULL;
+ return itr;
+}
+
+jsonObjectNode* jsonObjectIteratorNext( jsonObjectIterator* itr ) {
+ if(itr == NULL || itr->done) return NULL;
+
+ if(itr->current) free(itr->current);
+ jsonObject* next = jsonIteratorNext(itr->iterator);
+ if(next == NULL) {
+ itr->current = NULL;
+ itr->done = 1;
+ return NULL;
+ }
+ itr->current = makeNode(next, itr->iterator->index, itr->iterator->key);
+ return itr->current;
+}
+
+void jsonObjectIteratorFree(jsonObjectIterator* iter) {
+ if(iter->current) free(iter->current);
+ jsonIteratorFree(iter->iterator);
+ free(iter);
+}
+
+int jsonObjectIteratorHasNext(const jsonObjectIterator* itr) {
+ return (itr && itr->current);
+}
+
+
Modified: branches/autotools/src/libopensrf/osrf_message.c
===================================================================
--- branches/autotools/src/libopensrf/osrf_message.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/osrf_message.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -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 = NULL;
+
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,18 +13,36 @@
msg->is_exception = 0;
msg->_params = NULL;
msg->_result_content = NULL;
+ msg->sender_locale = NULL;
return msg;
}
-void osrf_message_set_method( osrf_message* msg, char* method_name ) {
+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) > sizeof(default_locale) - 1 ) return NULL;
+
+ strcpy( default_locale, locale );
+ return (const char*) default_locale;
+}
+
+void osrf_message_set_method( osrf_message* msg, const char* method_name ) {
if( msg == NULL || method_name == NULL ) return;
msg->method_name = strdup( method_name );
}
-void osrf_message_add_object_param( osrf_message* msg, jsonObject* o ) {
+void osrf_message_add_object_param( osrf_message* msg, const jsonObject* o ) {
if(!msg|| !o) return;
if(!msg->_params)
msg->_params = jsonParseString("[]");
@@ -30,16 +51,15 @@
free(j);
}
-void osrf_message_set_params( osrf_message* msg, jsonObject* o ) {
+void osrf_message_set_params( osrf_message* msg, const jsonObject* o ) {
if(!msg || !o) return;
if(o->type != JSON_ARRAY) {
osrfLogDebug( OSRF_LOG_MARK, "passing non-array to osrf_message_set_params(), fixing...");
+ if(msg->_params) jsonObjectFree(msg->_params);
jsonObject* clone = jsonObjectClone(o);
- o = jsonNewObject(NULL);
- jsonObjectPush(o, clone);
- if(msg->_params) jsonObjectFree(msg->_params);
- msg->_params = o;
+ msg->_params = jsonNewObject(NULL);
+ jsonObjectPush(msg->_params, clone);
return;
}
@@ -49,15 +69,15 @@
/* only works if parse_json_params is false */
-void osrf_message_add_param( osrf_message* msg, char* param_string ) {
+void osrf_message_add_param( osrf_message* msg, const char* param_string ) {
if(msg == NULL || param_string == NULL) return;
if(!msg->_params) msg->_params = jsonParseString("[]");
jsonObjectPush(msg->_params, jsonParseString(param_string));
}
-void osrf_message_set_status_info(
- osrf_message* msg, char* status_name, char* status_text, int status_code ) {
+void osrf_message_set_status_info( osrf_message* msg,
+ const char* status_name, const char* status_text, int status_code ) {
if(!msg) return;
if( status_name != NULL )
@@ -70,7 +90,7 @@
}
-void osrf_message_set_result_content( osrf_message* msg, char* json_string ) {
+void osrf_message_set_result_content( osrf_message* msg, const char* json_string ) {
if( msg == NULL || json_string == NULL) return;
msg->result_string = strdup(json_string);
if(json_string) msg->_result_content = jsonParseString(json_string);
@@ -101,6 +121,9 @@
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);
@@ -113,7 +136,7 @@
char* j;
int i = 0;
- osrfMessage* msg = NULL;
+ const osrfMessage* msg = NULL;
jsonObject* wrapper = jsonNewObject(NULL);
while( ((msg = msgs[i]) && (i++ < count)) )
@@ -126,7 +149,7 @@
}
-char* osrf_message_serialize(osrf_message* msg) {
+char* osrf_message_serialize(const osrf_message* msg) {
if( msg == NULL ) return NULL;
char* j = NULL;
@@ -144,18 +167,27 @@
}
-jsonObject* osrfMessageToJSON( osrfMessage* msg ) {
+jsonObject* osrfMessageToJSON( const osrfMessage* msg ) {
jsonObject* json = jsonNewObject(NULL);
jsonObjectSetClass(json, "osrfMessage");
jsonObject* payload;
- char sc[64]; memset(sc,0,64);
+ char sc[64];
+ osrf_clearbuf(sc, sizeof(sc));
char* str;
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:
@@ -171,7 +203,7 @@
payload = jsonNewObject(NULL);
jsonObjectSetClass(payload, msg->status_name);
jsonObjectSetKey(payload, "status", jsonNewObject(msg->status_text));
- sprintf(sc,"%d",msg->status_code);
+ snprintf(sc, sizeof(sc), "%d", msg->status_code);
jsonObjectSetKey(payload, "statusCode", jsonNewObject(sc));
jsonObjectSetKey(json, "payload", payload);
break;
@@ -193,7 +225,7 @@
payload = jsonNewObject(NULL);
jsonObjectSetClass(payload,"osrfResult");
jsonObjectSetKey(payload, "status", jsonNewObject(msg->status_text));
- sprintf(sc,"%d",msg->status_code);
+ snprintf(sc, sizeof(sc), "%d", msg->status_code);
jsonObjectSetKey(payload, "statusCode", jsonNewObject(sc));
str = jsonObjectToJSON(msg->_result_content);
jsonObjectSetKey(payload, "content", jsonParseString(str));
@@ -206,7 +238,7 @@
}
-int osrf_message_deserialize(char* string, osrf_message* msgs[], int count) {
+int osrf_message_deserialize(const char* string, osrf_message* msgs[], int count) {
if(!string || !msgs || count <= 0) return 0;
int numparsed = 0;
@@ -223,16 +255,16 @@
for( x = 0; x < json->size && x < count; x++ ) {
- jsonObject* message = jsonObjectGetIndex(json, x);
+ const jsonObject* message = jsonObjectGetIndex(json, x);
if(message && message->type != JSON_NULL &&
message->classname && !strcmp(message->classname, "osrfMessage")) {
osrf_message* new_msg = safe_malloc(sizeof(osrf_message));
- jsonObject* tmp = jsonObjectGetKey(message, "type");
+ const jsonObject* tmp = jsonObjectGetKeyConst(message, "type");
- char* t;
+ const char* t;
if( ( t = jsonObjectGetString(tmp)) ) {
if(!strcmp(t, "CONNECT")) new_msg->m_type = CONNECT;
@@ -242,49 +274,47 @@
if(!strcmp(t, "RESULT")) new_msg->m_type = RESULT;
}
- tmp = jsonObjectGetKey(message, "threadTrace");
+ tmp = jsonObjectGetKeyConst(message, "threadTrace");
if(tmp) {
char* tt = jsonObjectToSimpleString(tmp);
if(tt) {
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 */
+ if (current_locale)
+ free( current_locale );
- tmp = jsonObjectGetKey(message, "protocol");
+ tmp = jsonObjectGetKeyConst(message, "locale");
+ if(tmp) {
+ new_msg->sender_locale = jsonObjectToSimpleString(tmp);
+ current_locale = strdup( new_msg->sender_locale );
+ } else {
+ current_locale = NULL;
+ }
+ tmp = jsonObjectGetKeyConst(message, "protocol");
+
if(tmp) {
char* proto = jsonObjectToSimpleString(tmp);
if(proto) {
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");
+ tmp = jsonObjectGetKeyConst(message, "payload");
if(tmp) {
if(tmp->classname)
new_msg->status_name = strdup(tmp->classname);
- jsonObject* tmp0 = jsonObjectGetKey(tmp,"method");
+ const jsonObject* tmp0 = jsonObjectGetKeyConst(tmp,"method");
if(jsonObjectGetString(tmp0))
new_msg->method_name = strdup(jsonObjectGetString(tmp0));
- tmp0 = jsonObjectGetKey(tmp,"params");
+ tmp0 = jsonObjectGetKeyConst(tmp,"params");
if(tmp0) {
char* s = jsonObjectToJSON(tmp0);
new_msg->_params = jsonParseString(s);
@@ -293,11 +323,11 @@
free(s);
}
- tmp0 = jsonObjectGetKey(tmp,"status");
+ tmp0 = jsonObjectGetKeyConst(tmp,"status");
if(jsonObjectGetString(tmp0))
new_msg->status_text = strdup(jsonObjectGetString(tmp0));
- tmp0 = jsonObjectGetKey(tmp,"statusCode");
+ tmp0 = jsonObjectGetKeyConst(tmp,"statusCode");
if(tmp0) {
if(jsonObjectGetString(tmp0))
new_msg->status_code = atoi(jsonObjectGetString(tmp0));
@@ -305,7 +335,7 @@
new_msg->status_code = (int) jsonObjectGetNumber(tmp0);
}
- tmp0 = jsonObjectGetKey(tmp,"content");
+ tmp0 = jsonObjectGetKeyConst(tmp,"content");
if(tmp0) {
char* s = jsonObjectToJSON(tmp0);
new_msg->_result_content = jsonParseString(s);
Modified: branches/autotools/src/libopensrf/osrf_prefork.c
===================================================================
--- branches/autotools/src/libopensrf/osrf_prefork.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/osrf_prefork.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -210,7 +210,7 @@
/* if no data was reveived within the timeout interval */
if( !recvd && (end - start) >= keepalive ) {
- osrfLogInfo(OSRF_LOG_MARK, "No request was reveived in %d seconds, exiting stateful session", keepalive);
+ osrfLogInfo(OSRF_LOG_MARK, "No request was received in %d seconds, exiting stateful session", keepalive);
osrfAppSessionStatus(
session,
OSRF_STATUS_TIMEOUT,
@@ -547,9 +547,9 @@
/* now suck off the data */
char buf[64];
- memset( buf, 0, 64);
+ osrf_clearbuf( buf, sizeof(buf) );
if( (n=read(cur_child->read_status_fd, buf, 63)) < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "Read error afer select in child status read with errno %d", errno);
+ osrfLogWarning( OSRF_LOG_MARK, "Read error after select in child status read with errno %d", errno);
}
osrfLogDebug( OSRF_LOG_MARK, "Read %d bytes from status buffer: %s", n, buf );
@@ -566,7 +566,7 @@
int i,n;
growing_buffer* gbuf = buffer_init( READ_BUFSIZE );
char buf[READ_BUFSIZE];
- memset( buf, 0, READ_BUFSIZE );
+ osrf_clearbuf( buf, sizeof(buf) );
for( i = 0; i < child->max_requests; i++ ) {
@@ -579,7 +579,7 @@
if(!gotdata)
set_fl(child->read_data_fd, O_NONBLOCK );
buffer_add( gbuf, buf );
- memset( buf, 0, READ_BUFSIZE );
+ osrf_clearbuf( buf, sizeof(buf) );
gotdata = 1;
}
Modified: branches/autotools/src/libopensrf/osrf_settings.c
===================================================================
--- branches/autotools/src/libopensrf/osrf_settings.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/osrf_settings.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -2,7 +2,7 @@
osrf_host_config* config = NULL;
-char* osrf_settings_host_value(char* format, ...) {
+char* osrf_settings_host_value(const char* format, ...) {
VA_LIST_TO_STRING(format);
if( ! config ) {
@@ -18,7 +18,7 @@
return val;
}
-jsonObject* osrf_settings_host_value_object(char* format, ...) {
+jsonObject* osrf_settings_host_value_object(const char* format, ...) {
VA_LIST_TO_STRING(format);
if( ! config ) {
@@ -32,7 +32,7 @@
}
-int osrf_settings_retrieve(char* hostname) {
+int osrf_settings_retrieve(const char* hostname) {
if(!config) {
@@ -72,10 +72,11 @@
return 0;
}
-osrf_host_config* osrf_settings_new_host_config(char* hostname) {
+osrf_host_config* osrf_settings_new_host_config(const char* hostname) {
if(!hostname) return NULL;
osrf_host_config* c = safe_malloc(sizeof(osrf_host_config));
c->hostname = strdup(hostname);
+ c->config = NULL;
return c;
}
Modified: branches/autotools/src/libopensrf/osrf_stack.c
===================================================================
--- branches/autotools/src/libopensrf/osrf_stack.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/osrf_stack.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -67,7 +67,7 @@
osrf_app_session_set_remote( session, msg->sender );
osrf_message* arr[OSRF_MAX_MSGS_PER_PACKET];
- memset(arr, 0, OSRF_MAX_MSGS_PER_PACKET );
+ memset(arr, 0, sizeof(arr));
int num_msgs = osrf_message_deserialize(msg->body, arr, OSRF_MAX_MSGS_PER_PACKET);
osrfLogDebug( OSRF_LOG_MARK, "We received %d messages from %s", num_msgs, msg->sender );
@@ -92,7 +92,7 @@
} else {
osrfLogWarning( OSRF_LOG_MARK, " * Jabber Error is for top level remote id [%s], no one "
- "to send my message too!!!", session->remote_id );
+ "to send my message to!!!", session->remote_id );
}
}
Modified: branches/autotools/src/libopensrf/osrf_system.c
===================================================================
--- branches/autotools/src/libopensrf/osrf_system.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/osrf_system.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -4,9 +4,28 @@
#include <signal.h>
static int _osrfSystemInitCache( void );
+static void report_child_status( pid_t pid, int status );
+struct child_node;
+typedef struct child_node ChildNode;
+struct child_node
+{
+ ChildNode* pNext;
+ ChildNode* pPrev;
+ pid_t pid;
+ char* app;
+ char* libfile;
+};
+
+static ChildNode* child_list;
+
static transport_client* osrfGlobalTransportClient = NULL;
+static void add_child( pid_t pid, const char* app, const char* libfile );
+static void delete_child( ChildNode* node );
+static void delete_all_children( void );
+static ChildNode* seek_child( pid_t pid );
+
transport_client* osrfSystemGetTransportClient( void ) {
return osrfGlobalTransportClient;
}
@@ -122,12 +141,14 @@
pid_t pid;
if( (pid = fork()) ) {
- // storage pid in local table for re-launching dead children...
- osrfLogInfo( OSRF_LOG_MARK, "Launched application child %ld", (long) pid);
+ // store pid in local list for re-launching dead children...
+ add_child( pid, appname, libfile );
+ osrfLogInfo( OSRF_LOG_MARK, "Running application child %s: process id %ld",
+ appname, (long) pid );
} else {
- osrfLogError( OSRF_LOG_MARK, " * Running application %s\n", appname);
+ osrfLogInfo( OSRF_LOG_MARK, " * Running application %s\n", appname);
if( osrfAppRegisterApplication( appname, libfile ) == 0 )
osrf_prefork_run(appname);
@@ -140,7 +161,8 @@
while(1) {
errno = 0;
- pid_t pid = wait(NULL);
+ int status;
+ pid_t pid = wait( &status );
if(-1 == pid) {
if(errno == ECHILD)
osrfLogError(OSRF_LOG_MARK, "We have no more live services... exiting");
@@ -148,13 +170,131 @@
osrfLogError(OSRF_LOG_MARK, "Exiting top-level system loop with error: %s", strerror(errno));
break;
} else {
- osrfLogError(OSRF_LOG_MARK, "We lost a top-level service process with PID %ld", pid);
+ report_child_status( pid, status );
}
}
+ delete_all_children();
return 0;
}
+
+static void report_child_status( pid_t pid, int status )
+{
+ const char* app;
+ const char* libfile;
+ ChildNode* node = seek_child( pid );
+
+ if( node ) {
+ app = node->app ? node->app : "[unknown]";
+ libfile = node->libfile ? node->libfile : "[none]";
+ } else
+ app = libfile = NULL;
+
+ if( WIFEXITED( status ) )
+ {
+ int rc = WEXITSTATUS( status ); // return code of child process
+ if( rc )
+ osrfLogError( OSRF_LOG_MARK, "Child process %ld (app %s) exited with return code %d",
+ (long) pid, app, rc );
+ else
+ osrfLogInfo( OSRF_LOG_MARK, "Child process %ld (app %s) exited normally",
+ (long) pid, app );
+ }
+ else if( WIFSIGNALED( status ) )
+ {
+ osrfLogError( OSRF_LOG_MARK, "Child process %ld (app %s) killed by signal %d",
+ (long) pid, app, WTERMSIG( status) );
+ }
+ else if( WIFSTOPPED( status ) )
+ {
+ osrfLogError( OSRF_LOG_MARK, "Child process %ld (app %s) stopped by signal %d",
+ (long) pid, app, (int) WSTOPSIG( status ) );
+ }
+
+ delete_child( node );
+}
+
+/*----------- Routines to manage list of children --*/
+
+static void add_child( pid_t pid, const char* app, const char* libfile )
+{
+ /* Construct new child node */
+
+ ChildNode* node = safe_malloc( sizeof( ChildNode ) );
+
+ node->pid = pid;
+
+ if( app )
+ node->app = strdup( app );
+ else
+ node->app = NULL;
+
+ if( libfile )
+ node->libfile = strdup( libfile );
+ else
+ node->libfile = NULL;
+
+ /* Add new child node to the head of the list */
+
+ node->pNext = child_list;
+ node->pPrev = NULL;
+
+ if( child_list )
+ child_list->pPrev = node;
+
+ child_list = node;
+}
+
+static void delete_child( ChildNode* node ) {
+
+ /* Sanity check */
+
+ if( ! node )
+ return;
+
+ /* Detach the node from the list */
+
+ if( node->pPrev )
+ node->pPrev->pNext = node->pNext;
+ else
+ child_list = node->pNext;
+
+ if( node->pNext )
+ node->pNext->pPrev = node->pPrev;
+
+ /* Deallocate the node and its payload */
+
+ free( node->app );
+ free( node->libfile );
+ free( node );
+}
+
+static void delete_all_children( void ) {
+
+ while( child_list )
+ delete_child( child_list );
+}
+
+static ChildNode* seek_child( pid_t pid ) {
+
+ /* Return a pointer to the child node for the */
+ /* specified process ID, or NULL if not found */
+
+ ChildNode* node = child_list;
+ while( node ) {
+ if( node->pid == pid )
+ break;
+ else
+ node = node->pNext;
+ }
+
+ return node;
+}
+
+/*----------- End of routines to manage list of children --*/
+
+
int osrf_system_bootstrap_client_resc( char* config_file, char* contextnode, char* resource ) {
int failure = 0;
@@ -314,6 +454,7 @@
int osrf_system_shutdown( void ) {
osrfConfigCleanup();
+ osrfCacheCleanup();
osrf_system_disconnect_client();
osrf_settings_free_host_config(NULL);
osrfAppSessionCleanup();
Modified: branches/autotools/src/libopensrf/osrf_transgroup.c
===================================================================
--- branches/autotools/src/libopensrf/osrf_transgroup.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/osrf_transgroup.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -89,7 +89,7 @@
if(!(grp && msg)) return -1;
char domain[256];
- bzero(domain, 256);
+ osrf_clearbuf(domain, sizeof(domain));
jid_get_domain( msg->recipient, domain, 255 );
osrfTransportGroupNode* node = osrfHashGet(grp->nodes, domain);
@@ -108,15 +108,15 @@
int bufsize = 256;
char domain[bufsize];
- bzero(domain, bufsize);
+ osrf_clearbuf(domain, sizeof(domain));
jid_get_domain( msg->recipient, domain, bufsize - 1 );
char msgrecip[bufsize];
- bzero(msgrecip, bufsize);
+ osrf_clearbuf(msgrecip, sizeof(msgrecip));
jid_get_username(msg->recipient, msgrecip, bufsize - 1);
char msgres[bufsize];
- bzero(msgres, bufsize);
+ osrf_clearbuf(msgres, sizeof(msgres));
jid_get_resource(msg->recipient, msgres, bufsize - 1);
char* firstdomain = NULL;
@@ -149,8 +149,7 @@
/* update the recipient domain if necessary */
if(updateRecip) {
- bzero(newrcp, 1024);
- sprintf(newrcp, "%s@%s/%s", msgrecip, node->domain, msgres);
+ snprintf(newrcp, sizeof(newrcp), "%s@%s/%s", msgrecip, node->domain, msgres);
free(msg->recipient);
msg->recipient = strdup(newrcp);
}
Modified: branches/autotools/src/libopensrf/sha.c
===================================================================
--- branches/autotools/src/libopensrf/sha.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/sha.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -208,7 +208,7 @@
INT64 length=0;
int strsz;
- static char final[40];
+ static char final[41];
int *hashval;
hashval = (int *)malloc(20);
Modified: branches/autotools/src/libopensrf/socket_bundle.c
===================================================================
--- branches/autotools/src/libopensrf/socket_bundle.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/socket_bundle.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -707,7 +707,7 @@
int read_bytes;
int sock_fd = node->sock_fd;
- memset(buf, 0, RBUFSIZE);
+ osrf_clearbuf(buf, sizeof(buf));
set_fl(sock_fd, O_NONBLOCK);
osrfLogInternal( OSRF_LOG_MARK, "%ld : Received data at %f\n", (long) getpid(), get_timestamp_millis());
@@ -717,7 +717,7 @@
if(mgr->data_received)
mgr->data_received(mgr->blob, mgr, sock_fd, buf, node->parent_id);
- memset(buf, 0, RBUFSIZE);
+ osrf_clearbuf(buf, sizeof(buf));
}
int local_errno = errno; /* capture errno as set by recv() */
Modified: branches/autotools/src/libopensrf/string_array.c
===================================================================
--- branches/autotools/src/libopensrf/string_array.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/string_array.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -8,18 +8,11 @@
if(size > STRING_ARRAY_MAX_SIZE)
osrfLogError( OSRF_LOG_MARK, "init_string_array size is too large");
- /*
- string_array* arr =
- (string_array*) safe_malloc(sizeof(string_array));
- */
string_array* arr;
OSRF_MALLOC( arr, sizeof(string_array));
-
- //arr->array = (char**) safe_malloc(size * sizeof(char*));
- OSRF_MALLOC(arr->array, size * sizeof(char*));
-
+ arr->list = osrfNewListSize(size);
+ osrfListSetDefaultFree(arr->list);
arr->size = 0;
- arr->arr_size = size;
return arr;
}
@@ -30,65 +23,39 @@
void string_array_add(string_array* arr, char* str) {
if(arr == NULL || str == NULL ) return;
- if( strlen(str) < 1 ) return;
-
- arr->size++;
-
if( arr->size > STRING_ARRAY_MAX_SIZE )
osrfLogError( OSRF_LOG_MARK, "string_array_add size is too large");
-
- /* if necessary, double capacity */
- if(arr->size >= arr->arr_size) {
- arr->arr_size *= 2;
- //char** tmp = (char**) safe_malloc(arr->arr_size * sizeof(char*));
- char** tmp;
- OSRF_MALLOC( tmp, arr->arr_size * sizeof(char*));
- int i;
-
- /* copy the string pointers over */
- for( i = 0; i!= arr->size; i++ )
- tmp[i] = arr->array[i];
-
- free(arr->array);
- arr->array = tmp;
- }
-
- arr->array[arr->size - 1] = strdup(str);
+ osrfListPush(arr->list, strdup(str));
+ arr->size = arr->list->size;
}
char* osrfStringArrayGetString(osrfStringArray* arr, int index) {
- return string_array_get_string(arr, index);
+ if(!arr) return NULL;
+ return OSRF_LIST_GET_INDEX(arr->list, index);
}
char* string_array_get_string(string_array* arr, int index) {
- if(!arr || index < 0 || index >= arr->size ) return NULL;
- return arr->array[index];
+ if(!arr) return NULL;
+ return OSRF_LIST_GET_INDEX(arr->list, index);
}
void osrfStringArrayFree(osrfStringArray* arr) {
- string_array_destroy(arr);
+ OSRF_STRING_ARRAY_FREE(arr);
}
void string_array_destroy(string_array* arr) {
- if(arr) {
- int i = 0;
- while( i < arr->size ) free(arr->array[i++]);
- free(arr->array);
- free(arr);
- }
+ OSRF_STRING_ARRAY_FREE(arr);
}
int osrfStringArrayContains( osrfStringArray* arr, char* string ) {
if(!(arr && string)) return 0;
-
int i;
- for( i = 0; i != arr->size; i++ ) {
- char* str = osrfStringArrayGetString(arr, i);
- if(str) {
- if(!strcmp(str, string)) return 1;
- }
+ for( i = 0; i < arr->size; i++ ) {
+ char* str = OSRF_LIST_GET_INDEX(arr->list, i);
+ if(str && !strcmp(str, string))
+ return 1;
}
return 0;
@@ -97,19 +64,29 @@
void osrfStringArrayRemove( osrfStringArray* arr, char* tstr) {
if(!(arr && tstr)) return;
int i;
- for( i = 0; i != arr->size; i++ ) {
- char* str = osrfStringArrayGetString(arr, i);
- if(str) {
- if(!strcmp(str, tstr)) {
- free(arr->array[i]);
- arr->array[i] = NULL;
- break;
- }
+ char* str;
+
+ for( i = 0; i < arr->size; i++ ) {
+ /* find and remove the string */
+ str = OSRF_LIST_GET_INDEX(arr->list, i);
+ if(str && !strcmp(str, tstr)) {
+ osrfListRemove(arr->list, i);
+ break;
}
}
- for( ; i != arr->size; i++ )
- arr->array[i] = arr->array[i+1];
+ /* disable automatic item freeing on delete and shift
+ * items up in the array to fill in the gap
+ */
+ arr->list->freeItem = NULL;
+ for( ; i < arr->size - 1; i++ )
+ osrfListSet(arr->list, OSRF_LIST_GET_INDEX(arr->list, i+1) , i);
+
+ /* remove the last item since it was shifted up */
+ osrfListRemove(arr->list, i);
+
+ /* re-enable automatic item freeing in delete */
+ osrfListSetDefaultFree(arr->list);
arr->size--;
}
Modified: branches/autotools/src/libopensrf/transport_client.c
===================================================================
--- branches/autotools/src/libopensrf/transport_client.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/transport_client.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -23,7 +23,7 @@
if( recv->body ) {
int len = strlen(recv->body);
char buf[len + 20];
- memset( buf, 0, len + 20);
+ osrf_clearbuf( buf, 0, sizeof(buf));
sprintf( buf, "Echoing...%s", recv->body );
send = message_init( buf, "Echoing Stuff", "12345", recv->sender, "" );
} else {
Modified: branches/autotools/src/libopensrf/transport_message.c
===================================================================
--- branches/autotools/src/libopensrf/transport_message.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/transport_message.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -238,7 +238,7 @@
xmlAddChild( message_node, error_node );
xmlNewProp( error_node, BAD_CAST "type", BAD_CAST msg->error_type );
char code_buf[16];
- memset( code_buf, 0, 16);
+ osrf_clearbuf( code_buf, sizeof(code_buf));
sprintf(code_buf, "%d", msg->error_code );
xmlNewProp( error_node, BAD_CAST "code", BAD_CAST code_buf );
}
@@ -303,6 +303,7 @@
if( jid[i] == 64 ) { /*ascii @*/
if(i > size) i = size;
strncpy( buf, jid, i );
+ buf[i] = '\0'; // strncpy doesn't provide the nul
return;
}
}
@@ -319,6 +320,7 @@
int rlen = len - (i+1);
if(rlen > size) rlen = size;
strncpy( buf, start, rlen );
+ buf[rlen] = '\0'; // strncpy doesn't provide the nul
}
}
}
@@ -343,6 +345,7 @@
int dlen = index2 - index1;
if(dlen > size) dlen = size;
memcpy( buf, jid + index1, dlen );
+ buf[dlen] = '\0'; // memcpy doesn't provide the nul
}
}
Modified: branches/autotools/src/libopensrf/transport_session.c
===================================================================
--- branches/autotools/src/libopensrf/transport_session.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/transport_session.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -183,8 +183,7 @@
char* our_hostname = getenv("HOSTNAME");
size1 = 150 + strlen( server );
char stanza1[ size1 ];
- memset( stanza1, 0, size1 );
- sprintf( stanza1,
+ snprintf( stanza1, sizeof(stanza1),
"<stream:stream version='1.0' xmlns:stream='http://etherx.jabber.org/streams' "
"xmlns='jabber:component:accept' to='%s' from='%s' xml:lang='en'>",
username, our_hostname );
@@ -207,14 +206,12 @@
int ss = session->session_id->n_used + strlen(password) + 5;
char hashstuff[ss];
- memset(hashstuff,0,ss);
- sprintf( hashstuff, "%s%s", session->session_id->buf, password );
+ snprintf( hashstuff, sizeof(hashstuff), "%s%s", session->session_id->buf, password );
char* hash = shahash( hashstuff );
size2 = 100 + strlen( hash );
char stanza2[ size2 ];
- memset( stanza2, 0, size2 );
- sprintf( stanza2, "<handshake>%s</handshake>", hash );
+ snprintf( stanza2, sizeof(stanza2), "<handshake>%s</handshake>", hash );
//if( ! tcp_send( session->sock_obj, stanza2 ) ) {
if( socket_send( session->sock_id, stanza2 ) ) {
@@ -228,8 +225,7 @@
/* the first Jabber connect stanza */
size1 = 100 + strlen( server );
char stanza1[ size1 ];
- memset( stanza1, 0, size1 );
- sprintf( stanza1,
+ snprintf( stanza1, sizeof(stanza1),
"<stream:stream to='%s' xmlns='jabber:client' "
"xmlns:stream='http://etherx.jabber.org/streams'>",
server );
@@ -253,9 +249,7 @@
/* the second jabber connect stanza including login info*/
size2 = 150 + strlen( username ) + strlen(password) + strlen(resource);
char stanza2[ size2 ];
- memset( stanza2, 0, size2 );
-
- sprintf( stanza2,
+ snprintf( stanza2, sizeof(stanza2),
"<iq id='123456789' type='set'><query xmlns='jabber:iq:auth'>"
"<username>%s</username><password>%s</password><resource>%s</resource></query></iq>",
username, password, resource );
@@ -273,17 +267,14 @@
int ss = session->session_id->n_used + strlen(password) + 5;
char hashstuff[ss];
- memset(hashstuff,0,ss);
- sprintf( hashstuff, "%s%s", session->session_id->buf, password );
+ snprintf( hashstuff, sizeof(hashstuff), "%s%s", session->session_id->buf, password );
char* hash = shahash( hashstuff );
/* the second jabber connect stanza including login info*/
size2 = 150 + strlen( hash ) + strlen(password) + strlen(resource);
char stanza2[ size2 ];
- memset( stanza2, 0, size2 );
-
- sprintf( stanza2,
+ snprintf( stanza2, sizeof(stanza2),
"<iq id='123456789' type='set'><query xmlns='jabber:iq:auth'>"
"<username>%s</username><digest>%s</digest><resource>%s</resource></query></iq>",
username, hash, resource );
@@ -566,7 +557,6 @@
void *session, const xmlChar *ch, int len) {
char data[len+1];
- memset( data, 0, len+1 );
strncpy( data, (char*) ch, len );
data[len] = 0;
@@ -597,7 +587,7 @@
if( ses->state_machine->in_error ) {
/* for now... */
- osrfLogWarning( OSRF_LOG_MARK, "ERROR Xml fragment: %s\n", ch );
+ osrfLogWarning( OSRF_LOG_MARK, "ERROR XML fragment: %s\n", ch );
}
}
Modified: branches/autotools/src/libopensrf/utils.c
===================================================================
--- branches/autotools/src/libopensrf/utils.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/libopensrf/utils.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -22,6 +22,16 @@
osrfLogError( OSRF_LOG_MARK, "Out of Memory" );
exit(99);
}
+ memset( ptr, 0, size ); // remove this after safe_calloc transition
+ return ptr;
+}
+
+inline void* safe_calloc( int size ) {
+ void* ptr = (void*) malloc( size );
+ if( ptr == NULL ) {
+ osrfLogError( OSRF_LOG_MARK, "Out of Memory" );
+ exit(99);
+ }
memset( ptr, 0, size );
return ptr;
}
@@ -45,8 +55,9 @@
int i = 0;
while( i < argc ) {
int len = strlen( global_argv[i]);
- bzero( global_argv[i++], len );
+ osrf_clearbuf( global_argv[i], len );
global_argv_size += len;
+ i++;
}
global_argv_size -= 2;
@@ -55,7 +66,7 @@
int set_proc_title( char* format, ... ) {
VA_LIST_TO_STRING(format);
- bzero( *(global_argv), global_argv_size );
+ osrf_clearbuf( *(global_argv), global_argv_size);
return snprintf( *(global_argv), global_argv_size, VA_BUF );
}
@@ -121,7 +132,7 @@
len = va_list_size(format, args);
char buf[len];
- memset(buf, 0, len);
+ osrf_clearbuf(buf, sizeof(buf));
va_start(a_copy, format);
vsnprintf(buf, len - 1, format, a_copy);
@@ -164,7 +175,7 @@
len = va_list_size(format, args);
char buf[len];
- memset(buf, 0, len);
+ osrf_clearbuf(buf, sizeof(buf));
va_start(a_copy, format);
vsnprintf(buf, len - 1, format, a_copy);
@@ -212,7 +223,7 @@
int buffer_reset( growing_buffer *gb){
if( gb == NULL ) { return 0; }
if( gb->buf == NULL ) { return 0; }
- memset( gb->buf, 0, gb->size );
+ osrf_clearbuf( gb->buf, sizeof(gb->buf) );
gb->n_used = 0;
return 1;
}
@@ -416,7 +427,7 @@
int len = 1024;
char buf[len];
- bzero(buf, len);
+ osrf_clearbuf(buf, sizeof(buf));
growing_buffer* gb = buffer_init(len);
FILE* file = fopen(filename, "r");
@@ -425,9 +436,9 @@
return NULL;
}
- while(fgets(buf, len - 1, file)) {
+ while(fgets(buf, sizeof(buf), file)) {
buffer_add(gb, buf);
- bzero(buf, len);
+ osrf_clearbuf(buf, sizeof(buf));
}
fclose(file);
@@ -454,13 +465,11 @@
MD5_stop (&ctx, digest);
char buf[16];
- memset(buf,0,16);
-
char final[256];
- memset(final,0,256);
+ osrf_clearbuf(final, sizeof(final));
for ( i=0 ; i<16 ; i++ ) {
- sprintf(buf, "%02x", digest[i]);
+ snprintf(buf, sizeof(buf), "%02x", digest[i]);
strcat( final, buf );
}
Modified: branches/autotools/src/objson/json_parser.c
===================================================================
--- branches/autotools/src/objson/json_parser.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/objson/json_parser.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -482,7 +482,7 @@
"json_parse_json_string(): truncated escaped unicode"); }
char buff[5];
- memset(buff,0,5);
+ memset(buff, 0, sizeof(buff));
memcpy(buff, string + (*index), 4);
@@ -491,7 +491,7 @@
/* The following chunk was borrowed with permission from
json-c http://oss.metaparadigm.com/json-c/ */
unsigned char utf_out[4];
- memset(utf_out,0,4);
+ memset(utf_out, 0, sizeof(utf_out));
#define hexdigit(x) ( ((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
@@ -695,7 +695,7 @@
int json_handle_error(char* string, unsigned long* index, char* err_msg) {
char buf[60];
- memset(buf, 0, 60);
+ memset(buf, 0, sizeof(buf));
if(*index > 30)
strncpy( buf, string + (*index - 30), 59 );
Modified: branches/autotools/src/objson/objson_test.c
===================================================================
--- branches/autotools/src/objson/objson_test.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/objson/objson_test.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -183,11 +183,11 @@
char buf[10240];
char smallbuf[512];
- bzero(buf, 10240);
- bzero(smallbuf, 512);
+ memset(buf, 0, sizeof(buf));
+ memset(smallbuf, 0, sizeof(smallbuf));
- while(fgets(smallbuf, 512, F))
- strcat(buf, smallbuf);
+ while(fgets(smallbuf, sizeof(smallbuf), F))
+ strncat(buf, smallbuf, sizeof(buf) - 1);
/* dig our way into the JSON object we parsed, see test.json to get
an idea of the object structure */
Modified: branches/autotools/src/perlmods/OpenSRF/AppSession.pm
===================================================================
--- branches/autotools/src/perlmods/OpenSRF/AppSession.pm 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/perlmods/OpenSRF/AppSession.pm 2007-11-05 13:40:16 UTC (rev 1121)
@@ -156,6 +156,14 @@
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 @@
}
# 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 @@
my $app = shift;
my $api_level = shift;
my $quiet = shift;
+ my $locale = shift;
$api_level = 1 if (!defined($api_level));
@@ -237,6 +243,7 @@
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 @@
$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,7 @@
$logger->debug( "Number of matched responses: " . @list, DEBUG );
$self->queue_wait(0); # check for statuses
- return $list[0] unless (wantarray);
+ return $list[0] if (!wantarray);
return @list;
}
Modified: branches/autotools/src/perlmods/OpenSRF/Application.pm
===================================================================
--- branches/autotools/src/perlmods/OpenSRF/Application.pm 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/perlmods/OpenSRF/Application.pm 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,4 +1,5 @@
package OpenSRF::Application;
+# vim:noet:ts=4
use vars qw/$_app $log @_METHODS $thunk $server_class/;
use base qw/OpenSRF/;
@@ -98,7 +99,7 @@
my @p = $app_msg->params;
my $method_name = $app_msg->method;
my $method_proto = $session->last_message_api_level;
- $logger->info("CALL: $method_name [".join(', ', at p)."]");
+ $log->info("CALL: $method_name [". (@p ? join(', ', at p) : '') ."]");
my $coderef = $app->method_lookup( $method_name, $method_proto, 1, 1 );
Modified: branches/autotools/src/perlmods/OpenSRF/DomainObject/oilsMessage.pm
===================================================================
--- branches/autotools/src/perlmods/OpenSRF/DomainObject/oilsMessage.pm 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/perlmods/OpenSRF/DomainObject/oilsMessage.pm 2007-11-05 13:40:16 UTC (rev 1121)
@@ -86,6 +86,24 @@
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
@@ -163,12 +181,14 @@
my $session = shift;
my $mtype = $self->type;
+ my $locale = $self->sender_locale;
my $api_level = $self->api_level || 1;;
my $tT = $self->threadTrace;
$session->last_message_type($mtype);
$session->last_message_api_level($api_level);
$session->last_threadTrace($tT);
+ $session->session_locale($locale);
$log->debug(" Received api_level => [$api_level], MType => [$mtype], ".
"from [".$session->remote_id."], threadTrace[".$self->threadTrace."]");
Modified: branches/autotools/src/perlmods/OpenSRF/DomainObject/oilsResponse.pm
===================================================================
--- branches/autotools/src/perlmods/OpenSRF/DomainObject/oilsResponse.pm 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/perlmods/OpenSRF/DomainObject/oilsResponse.pm 2007-11-05 13:40:16 UTC (rev 1121)
@@ -201,7 +201,7 @@
=head1 ABSTRACT
Implements the STATUS_CONTINUE message, informing the client that it should
-continue to wait for a response to it's request.
+continue to wait for a response to its request.
=head1 SEE ALSO
@@ -316,11 +316,11 @@
The base class for Exception messages sent between client and server. This
is implemented on top of the C<OpenSRF::DomainObject::oilsResponse> class, and
-sets the default B<status> to C<Exception occured> and B<statusCode> to C<STATUS_BADREQUEST>.
+sets the default B<status> to C<Exception occurred> and B<statusCode> to C<STATUS_BADREQUEST>.
=cut
-$status = 'Exception occured';
+$status = 'Exception occurred';
$statusCode = STATUS_INTERNALSERVERERROR;
#-------------------------------------------------------------------------------
@@ -372,7 +372,7 @@
=head1 NAME
-OpenSRF::DomainObject::oilsMehtodException
+OpenSRF::DomainObject::oilsMethodException
=head1 SYNOPSIS
@@ -387,7 +387,7 @@
=head1 ABSTRACT
-The class for Exceptions that occur durring the B<CONNECT> phase of a session. This
+The class for Exceptions that occur during the B<CONNECT> phase of a session. This
is implemented on top of the C<OpenSRF::DomainObject::oilsException> class, and
sets the default B<status> to C<Connect Request Failed> and B<statusCode> to C<STATUS_NOTFOUND>.
@@ -398,7 +398,7 @@
=cut
-$status = 'A server error occured during method execution';
+$status = 'A server error occurred during method execution';
$statusCode = STATUS_INTERNALSERVERERROR;
# -------------------------------------------
Modified: branches/autotools/src/perlmods/OpenSRF/Transport.pm
===================================================================
--- branches/autotools/src/perlmods/OpenSRF/Transport.pm 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/perlmods/OpenSRF/Transport.pm 2007-11-05 13:40:16 UTC (rev 1121)
@@ -90,7 +90,7 @@
my $body = $helper->get_body();
my $type = $helper->get_msg_type();
- $logger->set_osrf_xid($helper->get_osrf_xid);
+ $logger->set_osrf_xid($helper->get_osrf_xid);
if (defined($type) and $type eq 'error') {
throw OpenSRF::EX::Session ("$remote_id IS NOT CONNECTED TO THE NETWORK!!!");
Modified: branches/autotools/src/perlmods/OpenSRF/UnixServer.pm
===================================================================
--- branches/autotools/src/perlmods/OpenSRF/UnixServer.pm 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/perlmods/OpenSRF/UnixServer.pm 2007-11-05 13:40:16 UTC (rev 1121)
@@ -146,7 +146,7 @@
$logger->debug( "Looping on zombies " . $x++ , DEBUG);
}
- $logger->debug( "Timed out, disconnected, or auth failed" );
+ $logger->debug( "Timed out, disconnected, or authentication failed" );
$app_session->kill_me if ($app_session);
$0 = $orig;
@@ -203,7 +203,7 @@
# boot a client
OpenSRF::System->bootstrap_client( client_name => "system_client" );
- $logger->debug( "Setting application implementaion for $app", DEBUG );
+ $logger->debug( "Setting application implementation for $app", DEBUG );
my $client = OpenSRF::Utils::SettingsClient->new();
my $imp = $client->config_value("apps", $app, "implementation");
OpenSRF::Application::server_class($app);
Modified: branches/autotools/src/perlmods/OpenSRF/Utils/JSON.pm
===================================================================
--- branches/autotools/src/perlmods/OpenSRF/Utils/JSON.pm 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/perlmods/OpenSRF/Utils/JSON.pm 2007-11-05 13:40:16 UTC (rev 1121)
@@ -85,8 +85,80 @@
return $hint;
}
+
+my $JSON_CLASS_KEY = '__c';
+my $JSON_PAYLOAD_KEY = '__p';
+
sub JSON2perl {
+ my( $class, $string ) = @_;
+ my $perl = $class->rawJSON2perl($string);
+ return $class->JSONObject2Perl($perl);
+}
+
+sub perl2JSON {
+ my( $class, $obj ) = @_;
+ my $json = $class->perl2JSONObject($obj);
+ return $class->rawPerl2JSON($json);
+}
+
+sub JSONObject2Perl {
my $class = shift;
+ my $obj = shift;
+ my $ref = ref($obj);
+ if( $ref eq 'HASH' ) {
+ if( defined($obj->{$JSON_CLASS_KEY})) {
+ my $cls = $obj->{$JSON_CLASS_KEY};
+ $cls =~ s/^\s+//o;
+ $cls =~ s/\s+$//o;
+ if( $obj = $class->JSONObject2Perl($obj->{$JSON_PAYLOAD_KEY}) ) {
+ $cls = $class->lookup_class($cls) || $cls;
+ return bless(\$obj, $cls) unless ref($obj);
+ return bless($obj, $cls);
+ }
+ return undef;
+ }
+ $obj->{$_} = $class->JSONObject2Perl($obj->{$_}) for (keys %$obj);
+ } elsif( $ref eq 'ARRAY' ) {
+ $obj->[$_] = $class->JSONObject2Perl($obj->[$_]) for(0..scalar(@$obj) - 1);
+ }
+ return $obj;
+}
+
+sub perl2JSONObject {
+ my $class = shift;
+ my $obj = shift;
+ my $ref = ref($obj);
+
+ return $obj unless $ref;
+ my $newobj;
+
+ if( $ref eq 'HASH' ) {
+ $newobj = {};
+ $newobj->{$_} = $class->perl2JSONObject( $obj->{$_} ) for (keys %$obj);
+ } elsif( $ref eq 'ARRAY' ) {
+ $newobj = [];
+ $newobj->[$_] = $class->perl2JSONObject( $obj->[$_] ) for(0..scalar(@$obj) - 1 );
+ } elsif( $ref ) {
+ if(UNIVERSAL::isa($obj, 'HASH')) {
+ $newobj = {};
+ $newobj->{$_} = $class->perl2JSONObject( $obj->{$_} ) for (keys %$obj);
+ bless( $newobj, ref($obj) );
+ #bless($obj, 'HASH'); # so our parser won't add the hints
+ } elsif(UNIVERSAL::isa($obj, 'ARRAY')) {
+ $newobj = [];
+ $newobj->[$_] = $class->perl2JSONObject( $obj->[$_] ) for(0..scalar(@$obj) - 1);
+ bless( $newobj, ref($obj) );
+ #bless($obj, 'ARRAY'); # so our parser won't add the hints
+ }
+ $ref = $class->lookup_hint($ref) || $ref;
+ $newobj = { $JSON_CLASS_KEY => $ref, $JSON_PAYLOAD_KEY => $newobj };
+ }
+ return $newobj;
+}
+
+
+sub rawJSON2perl {
+ my $class = shift;
local $_ = shift;
s/(?<!\\)\$/\\\$/gmo; # fixup $ for later
@@ -97,8 +169,8 @@
s/\\u([0-9a-fA-F]{4})/chr(hex($1))/esog;
# handle class blessings
- s/\/\*--\s*S\w*?\s+\S+\s*--\*\// bless(/sog;
- s/(\]|\}|")\s*\/\*--\s*E\w*?\s+(\S+)\s*--\*\//$1 => _json_hint_to_class("$1", "$2")) /sog;
+# s/\/\*--\s*S\w*?\s+\S+\s*--\*\// bless(/sog;
+# s/(\]|\}|")\s*\/\*--\s*E\w*?\s+(\S+)\s*--\*\//$1 => _json_hint_to_class("$1", "$2")) /sog;
my $re = qr/((?<!\\)"(?>(?<=\\)"|[^"])*(?<!\\)")/;
# Grab strings...
@@ -112,17 +184,18 @@
s/:/ => /sog;
# Do numbers...
- #s/\b(-?\d+\.?\d*)\b/ OpenSRF::Utils::JSON::number::new($1) /sog;
+ #s/\b(-?\d+\.?\d*)\b/ JSON::number::new($1) /sog;
# Change javascript stuff to perl...
s/null/ undef /sog;
- s/true/ bless( {}, "OpenSRF::Utils::JSON::bool::true") /sog;
- s/false/ bless( {}, "OpenSRF::Utils::JSON::bool::false") /sog;
+ s/true/ bless( {}, "JSON::bool::true") /sog;
+ s/false/ bless( {}, "JSON::bool::false") /sog;
my $ret;
return eval '$ret = '.$_;
}
+
my $_json_index;
sub ___JSON2perl {
my $class = shift;
@@ -638,7 +711,7 @@
} elsif ($element =~ /^\/\*/) {
next;
} elsif ($element =~ /^\d/) {
- $output .= "do { OpenSRF::Utils::JSON::number::new($element) }";
+ $output .= "do { JSON::number::new($element) }";
next;
} elsif ($element eq '{' or $element eq '[') {
$casting_depth++;
@@ -654,10 +727,10 @@
$output .= ' => ';
next;
} elsif ($element eq 'true') {
- $output .= 'bless( {}, "OpenSRF::Utils::JSON::bool::true")';
+ $output .= 'bless( {}, "JSON::bool::true")';
next;
} elsif ($element eq 'false') {
- $output .= 'bless( {}, "OpenSRF::Utils::JSON::bool::false")';
+ $output .= 'bless( {}, "JSON::bool::false")';
next;
}
@@ -667,26 +740,28 @@
return eval $output;
}
-sub perl2JSON {
+
+sub rawPerl2JSON {
my ($class, $perl, $strict) = @_;
my $output = '';
if (!defined($perl)) {
$output = '' if $strict;
$output = 'null' unless $strict;
- } elsif (ref($perl) and ref($perl) =~ /^OpenSRF::Utils::JSON/) {
+ } elsif (ref($perl) and ref($perl) =~ /^JSON/) {
$output .= $perl;
- } elsif ( ref($perl) && exists($_class_map{classes}{ref($perl)}) ) {
- $output .= '/*--S '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
- if (lc($_class_map{classes}{ref($perl)}{type}) eq 'hash') {
- my %hash = %$perl;
- $output .= perl2JSON(undef,\%hash, $strict);
- } elsif (lc($_class_map{classes}{ref($perl)}{type}) eq 'array') {
- my @array = @$perl;
- $output .= perl2JSON(undef,\@array, $strict);
- }
- $output .= '/*--E '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
- } elsif (ref($perl) and ref($perl) =~ /HASH/) {
+# } elsif ( ref($perl) && exists($_class_map{classes}{ref($perl)}) ) {
+# $output .= '/*--S '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
+# if (lc($_class_map{classes}{ref($perl)}{type}) eq 'hash') {
+# my %hash = %$perl;
+# $output .= rawPerl2JSON(undef,\%hash, $strict);
+# } elsif (lc($_class_map{classes}{ref($perl)}{type}) eq 'array') {
+# my @array = @$perl;
+# $output .= rawPerl2JSON(undef,\@array, $strict);
+# }
+# $output .= '/*--E '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
+# } elsif (ref($perl) and ref($perl) =~ /HASH/) {
+ } elsif (UNIVERSAL::isa($perl, 'HASH')) {
$output .= '{';
my $c = 0;
for my $key (sort keys %$perl) {
@@ -701,27 +776,28 @@
$outkey =~ s/\n/\\n/sgo;
$outkey =~ s/([\x{0080}-\x{fffd}])/sprintf('\u%0.4x',ord($1))/sgoe;
- $output .= '"'.$outkey.'":'. perl2JSON(undef,$$perl{$key}, $strict);
+ $output .= '"'.$outkey.'":'. rawPerl2JSON(undef,$$perl{$key}, $strict);
$c++;
}
$output .= '}';
- } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
+# } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
+ } elsif (UNIVERSAL::isa($perl, 'ARRAY')) {
$output .= '[';
my $c = 0;
for my $part (@$perl) {
$output .= ',' if ($c);
- $output .= perl2JSON(undef,$part, $strict);
+ $output .= rawPerl2JSON(undef,$part, $strict);
$c++;
}
$output .= ']';
} elsif (ref($perl) and ref($perl) =~ /CODE/) {
- $output .= perl2JSON(undef,$perl->(), $strict);
+ $output .= rawPerl2JSON(undef,$perl->(), $strict);
} elsif (ref($perl) and ("$perl" =~ /^([^=]+)=(\w+)/o)) {
my $type = $2;
my $name = $1;
OpenSRF::Utils::JSON->register_class_hint(name => $name, hint => $name, type => lc($type));
- $output .= perl2JSON(undef,$perl, $strict);
+ $output .= rawPerl2JSON(undef,$perl, $strict);
} else {
$perl = NFC($perl);
$perl =~ s{\\}{\\\\}sgo;
@@ -750,7 +826,7 @@
if (!defined($perl)) {
$output = " "x$depth unless($nospace);
$output .= 'null';
- } elsif (ref($perl) and ref($perl) =~ /^OpenSRF::Utils::JSON/) {
+ } elsif (ref($perl) and ref($perl) =~ /^JSON/) {
$output = " "x$depth unless($nospace);
$output .= $perl;
} elsif ( ref($perl) && exists($_class_map{classes}{ref($perl)}) ) {
Modified: branches/autotools/src/perlmods/OpenSRF/Utils/Logger.pm
===================================================================
--- branches/autotools/src/perlmods/OpenSRF/Utils/Logger.pm 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/perlmods/OpenSRF/Utils/Logger.pm 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,4 +1,5 @@
package OpenSRF::Utils::Logger;
+# vim:ts=4:noet:
use strict;
use vars qw($AUTOLOAD @EXPORT_OK %EXPORT_TAGS);
use Exporter;
@@ -29,7 +30,7 @@
%EXPORT_TAGS = ( level => [ qw/ NONE ERROR WARN INFO DEBUG INTERNAL / ], logger => [ '$logger' ] );
my $config; # config handle
-my $loglevel; # global log level
+my $loglevel = INFO(); # global log level
my $logfile; # log file
my $facility; # syslog facility
my $actfac; # activity log syslog facility
@@ -101,8 +102,12 @@
$actfile = $config->bootstrap->actlog || $config->bootstrap->logfile;
}
-
- $isclient = (OpenSRF::Utils::Config->current->bootstrap->client =~ /^true$/iog) ? 1 : 0;
+ my $client = OpenSRF::Utils::Config->current->bootstrap->client();
+ if (!$client) {
+ $isclient = 0;
+ return;
+ }
+ $isclient = ($client =~ /^true$/iog) ? 1 : 0;
}
sub _fac_to_const {
Modified: branches/autotools/src/python/osrf/gateway.py
===================================================================
--- branches/autotools/src/python/osrf/gateway.py 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/python/osrf/gateway.py 2007-11-05 13:40:16 UTC (rev 1121)
@@ -2,17 +2,21 @@
from xml.sax import handler, make_parser, saxutils
from json import *
from net_obj import *
+from log import *
import urllib, urllib2, sys, re
defaultHost = None
-#paramRegex = re.compile('\%27')
class GatewayRequest:
def __init__(self, service, method, params=[]):
self.service = service
self.method = method
self.params = params
+ self.path = 'gateway'
+ def setPath(self, path):
+ self.path = path
+
def send(self):
params = self.buildPOSTParams()
request = urllib2.Request(self.buildURL(), data=params)
@@ -45,9 +49,34 @@
setDefaultHost = staticmethod(setDefaultHost)
def buildURL(self):
- return 'http://%s/gateway' % defaultHost
+ return 'http://%s/%s' % (defaultHost, self.path)
+class JSONGatewayRequest(GatewayRequest):
+ def __init__(self, service, method, *params):
+ GatewayRequest.__init__(self, service, method, list(params))
+ def getFormat(self):
+ return 'json'
+
+ def getInputFormat(self):
+ return self.getFormat()
+
+ def handleResponse(self, response):
+ s = response.read()
+ obj = osrfJSONToObject(s)
+ if obj['status'] != 200:
+ sys.stderr.write('JSON gateway returned status %d:\n%s\n' % (obj['status'], s))
+ return None
+
+ # the gateway wraps responses in an array to handle streaming data
+ # if there is only one item in the array, it (probably) wasn't a streaming request
+ p = obj['payload']
+ if len(p) > 1: return p
+ return p[0]
+
+ def encodeParam(self, param):
+ return osrfObjectToJSON(param)
+
class XMLGatewayRequest(GatewayRequest):
def __init__(self, service, method, *params):
@@ -63,7 +92,12 @@
handler = XMLGatewayParser()
parser = make_parser()
parser.setContentHandler(handler)
- parser.parse(response)
+ try:
+ parser.parse(response)
+ except Exception, e:
+ osrfLogErr('Error parsing gateway XML: %s' % str(e))
+ return None
+
return handler.getResult()
def encodeParam(self, param):
Modified: branches/autotools/src/python/osrf/json.py
===================================================================
--- branches/autotools/src/python/osrf/json.py 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/python/osrf/json.py 2007-11-05 13:40:16 UTC (rev 1121)
@@ -4,10 +4,21 @@
class osrfJSONNetworkEncoder(simplejson.JSONEncoder):
def default(self, obj):
+
if isinstance(obj, osrfNetworkObject):
+ reg = obj.getRegistry()
+ data = obj.getData()
+
+ # re-encode the object as an array if necessary
+ if reg.wireProtocol == 'array':
+ d = []
+ for k in reg.keys:
+ d.append(data.get(k))
+ data = d
+
return {
- OSRF_JSON_CLASS_KEY: obj.getRegistry().hint,
- OSRF_JSON_PAYLOAD_KEY: self.default(obj.getData())
+ OSRF_JSON_CLASS_KEY: reg.hint,
+ OSRF_JSON_PAYLOAD_KEY: self.default(data)
}
return obj
@@ -77,9 +88,15 @@
instring = False
inescape = False
done = False
+ eatws = False
for c in json:
+ if eatws: # simpljson adds a pesky space after array and object items
+ if c == ' ':
+ continue
+
+ eatws = False
done = False
if (c == '{' or c == '[') and not instring:
t += 1
@@ -94,7 +111,11 @@
if c == ',' and not instring:
r += c + '\n' + __tabs(t)
done = True
+ eatws = True
+ if c == ':' and not instring:
+ eatws = True
+
if c == '"' and not inescape:
instring = not instring
Modified: branches/autotools/src/python/osrf/log.py
===================================================================
--- branches/autotools/src/python/osrf/log.py 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/python/osrf/log.py 2007-11-05 13:40:16 UTC (rev 1121)
@@ -13,7 +13,7 @@
# GNU General Public License for more details.
# -----------------------------------------------------------------------
-import traceback, sys, os, re
+import traceback, sys, os, re, threading
from osrf.const import *
loglevel = 4
@@ -50,6 +50,8 @@
try:
import syslog
except:
+ if level == OSRF_LOG_ERR:
+ sys.stderr.write('ERR ' + msg)
return
global loglevel
@@ -66,8 +68,11 @@
if level == OSRF_LOG_WARN: lvl = 'WARN'; slvl=syslog.LOG_WARNING
if level == OSRF_LOG_ERR: lvl = 'ERR '; slvl=syslog.LOG_ERR
+
+ # XXX when file logging is implemented, wrap io in a semaphore for thread safety
+
file = frgx.sub('',tb[0])
- msg = '[%s:%d:%s:%s] %s' % (lvl, os.getpid(), file, tb[1], msg)
+ msg = '[%s:%d:%s:%s:%s] %s' % (lvl, os.getpid(), file, tb[1], threading.currentThread().getName(), msg)
syslog.syslog(slvl, msg)
if level == OSRF_LOG_ERR:
Modified: branches/autotools/src/python/osrf/net.py
===================================================================
--- branches/autotools/src/python/osrf/net.py 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/python/osrf/net.py 2007-11-05 13:40:16 UTC (rev 1121)
@@ -19,129 +19,133 @@
from pyxmpp.jid import JID
from socket import gethostname
from osrf.log import *
-import os, time
+import os, time, threading
import logging
+threadSessions = {}
+
# - log jabber activity (for future reference)
#logger=logging.getLogger()
#logger.addHandler(logging.StreamHandler())
#logger.addHandler(logging.FileHandler('j.log'))
#logger.setLevel(logging.DEBUG)
-__network = None
def osrfSetNetworkHandle(handle):
- """Sets the global network connection handle."""
- global __network
- __network = handle
+ """ Sets the thread-specific network handle"""
+ threadSessions[threading.currentThread().getName()] = handle
def osrfGetNetworkHandle():
- """Returns the global network connection handle."""
- global __network
- return __network
+ """ Returns the thread-specific network connection handle."""
+ return threadSessions.get(threading.currentThread().getName())
class osrfNetworkMessage(object):
- """Network message
+ """Network message
- attributes:
+ attributes:
- sender - message sender
- to - message recipient
- body - the body of the message
- thread - the message thread
- """
+ sender - message sender
+ to - message recipient
+ body - the body of the message
+ thread - the message thread
+ """
- def __init__(self, message=None, **args):
- if message:
- self.body = message.get_body()
- self.thread = message.get_thread()
- self.to = message.get_to()
- if message.xmlnode.hasProp('router_from') and message.xmlnode.prop('router_from') != '':
- self.sender = message.xmlnode.prop('router_from')
- else: self.sender = message.get_from().as_utf8()
- else:
- if args.has_key('sender'): self.sender = args['sender']
- if args.has_key('to'): self.to = args['to']
- if args.has_key('body'): self.body = args['body']
- if args.has_key('thread'): self.thread = args['thread']
+ def __init__(self, message=None, **args):
+ if message:
+ self.body = message.get_body()
+ self.thread = message.get_thread()
+ self.to = message.get_to()
+ if message.xmlnode.hasProp('router_from') and message.xmlnode.prop('router_from') != '':
+ self.sender = message.xmlnode.prop('router_from')
+ else: self.sender = message.get_from().as_utf8()
+ else:
+ if args.has_key('sender'): self.sender = args['sender']
+ if args.has_key('to'): self.to = args['to']
+ if args.has_key('body'): self.body = args['body']
+ if args.has_key('thread'): self.thread = args['thread']
class osrfNetwork(JabberClient):
- def __init__(self, **args):
- self.isconnected = False
+ def __init__(self, **args):
+ self.isconnected = False
- # Create a unique jabber resource
- resource = 'osrf_client'
- if args.has_key('resource'):
- resource = args['resource']
- resource += '_' + gethostname()+':'+ str(os.getpid())
- self.jid = JID(args['username'], args['host'], resource)
+ # Create a unique jabber resource
+ resource = 'python'
+ if args.has_key('resource'):
+ resource = args['resource']
+ resource += '_' + gethostname()+':'+ str(os.getpid()) + '_'+ threading.currentThread().getName().lower()
+ self.jid = JID(args['username'], args['host'], resource)
- osrfLogDebug("initializing network with JID %s and host=%s, port=%s, username=%s" %
- (self.jid.as_utf8(), args['host'], args['port'], args['username']))
+ osrfLogDebug("initializing network with JID %s and host=%s, port=%s, username=%s" %
+ (self.jid.as_utf8(), args['host'], args['port'], args['username']))
- #initialize the superclass
- JabberClient.__init__(self, self.jid, args['password'], args['host'])
- self.queue = []
+ #initialize the superclass
+ JabberClient.__init__(self, self.jid, args['password'], args['host'])
+ self.queue = []
- def connect(self):
- JabberClient.connect(self)
- while not self.isconnected:
- stream = self.get_stream()
- act = stream.loop_iter(10)
- if not act: self.idle()
+ self.recvCallback = None
- def setRecvCallback(self, func):
- """The callback provided is called when a message is received.
-
- The only argument to the function is the received message. """
- self.recvCallback = func
+ def connect(self):
+ JabberClient.connect(self)
+ while not self.isconnected:
+ stream = self.get_stream()
+ act = stream.loop_iter(10)
+ if not act: self.idle()
- def session_started(self):
- osrfLogInfo("Successfully connected to the opensrf network")
- self.authenticated()
- self.stream.set_message_handler("normal",self.message_received)
- self.isconnected = True
+ def setRecvCallback(self, func):
+ """The callback provided is called when a message is received.
+
+ The only argument to the function is the received message. """
+ self.recvCallback = func
- def send(self, message):
- """Sends the provided network message."""
- osrfLogInternal("jabber sending to %s: %s" % (message.to, message.body))
- msg = Message(None, None, message.to, None, None, None, message.body, message.thread)
- self.stream.send(msg)
-
- def message_received(self, stanza):
- """Handler for received messages."""
- osrfLogInternal("jabber received a message of type %s" % stanza.get_type())
- if stanza.get_type()=="headline":
- return True
- # check for errors
- osrfLogInternal("jabber received message from %s : %s"
- % (stanza.get_from().as_utf8(), stanza.get_body()))
- self.queue.append(osrfNetworkMessage(stanza))
- return True
+ def session_started(self):
+ osrfLogInfo("Successfully connected to the opensrf network")
+ self.authenticated()
+ self.stream.set_message_handler("normal",self.message_received)
+ self.isconnected = True
- def recv(self, timeout=120):
- """Attempts to receive a message from the network.
+ def send(self, message):
+ """Sends the provided network message."""
+ osrfLogInternal("jabber sending to %s: %s" % (message.to, message.body))
+ msg = Message(None, None, message.to, None, None, None, message.body, message.thread)
+ self.stream.send(msg)
+
+ def message_received(self, stanza):
+ """Handler for received messages."""
+ osrfLogInternal("jabber received a message of type %s" % stanza.get_type())
+ if stanza.get_type()=="headline":
+ return True
+ # check for errors
+ osrfLogInternal("jabber received message from %s : %s"
+ % (stanza.get_from().as_utf8(), stanza.get_body()))
+ self.queue.append(osrfNetworkMessage(stanza))
+ return True
- timeout - max number of seconds to wait for a message.
- If no message is received in 'timeout' seconds, None is returned. """
+ def recv(self, timeout=120):
+ """Attempts to receive a message from the network.
- msg = None
- if len(self.queue) == 0:
- while timeout >= 0 and len(self.queue) == 0:
- starttime = time.time()
- osrfLogInternal("going into stream loop at " + str(starttime))
- act = self.get_stream().loop_iter(timeout)
- endtime = time.time() - starttime
- timeout -= endtime
- osrfLogInternal("exiting stream loop after %s seconds" % str(endtime))
- osrfLogInternal("act = %s : queue length = %d" % (act, len(self.queue)) )
- if not act: self.idle()
+ timeout - max number of seconds to wait for a message.
+ If a message is received in 'timeout' seconds, the message is passed to
+ the recvCallback is called and True is returned. Otherwise, false is returned."""
- # if we've acquired a message, handle it
- if len(self.queue) > 0:
- self.recvCallback(self.queue.pop(0))
- return None
+ msg = None
+ if len(self.queue) == 0:
+ while timeout >= 0 and len(self.queue) == 0:
+ starttime = time.time()
+ osrfLogInternal("going into stream loop at " + str(starttime))
+ act = self.get_stream().loop_iter(timeout)
+ endtime = time.time() - starttime
+ timeout -= endtime
+ osrfLogInternal("exiting stream loop after %s seconds" % str(endtime))
+ osrfLogInternal("act = %s : queue length = %d" % (act, len(self.queue)) )
+ if not act: self.idle()
+ # if we've acquired a message, handle it
+ if len(self.queue) > 0:
+ self.recvCallback(self.queue.pop(0))
+ return True
+ return False
+
+
Modified: branches/autotools/src/python/osrf/net_obj.py
===================================================================
--- branches/autotools/src/python/osrf/net_obj.py 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/python/osrf/net_obj.py 2007-11-05 13:40:16 UTC (rev 1121)
@@ -2,20 +2,11 @@
from xml.sax import saxutils
-class osrfNetworkObject(object):
- ''' Base class for all network serializable objects '''
- pass
+# -----------------------------------------------------------
+# Define the global network-class registry
+# -----------------------------------------------------------
-def osrfNewObjectFromHint(hint):
- try:
- obj = None
- exec('obj = osrfNetworkObject.%s()' % hint)
- return obj
- except AttributeError:
- return osrfNetworkObject.__unknown()
-
-
-''' Global object registry '''
+# Global object registry
objectRegistry = {}
class osrfNetworkRegistry(object):
@@ -37,56 +28,79 @@
getRegistry = staticmethod(getRegistry)
-def __makeNetworkAccessor(cls, key):
- ''' Creates and accessor/mutator method for the given class.
+# -----------------------------------------------------------
+# Define the base class for all network-serializable objects
+# -----------------------------------------------------------
- 'key' is the name the method will have and represents
- the field on the object whose data we are accessing
- '''
- def accessor(self, *args):
- if len(args) != 0:
- self.__data[key] = args[0]
- return self.__data.get(key)
- setattr(cls, key, accessor)
+class osrfNetworkObject(object):
+ ''' Base class for all network serializable objects '''
+ # link to our registry object for this registered class
+ registry = None
+ def __init__(self, data=None):
+ ''' If this is an array, we pull data out of the data array
+ (if there is any) and translate that into a hash internally '''
-def __makeGetRegistry(cls, registry):
- ''' Wraps the registry for this class inside an accessor method '''
- def get(self):
- return registry
- setattr(cls, 'getRegistry', get)
+ self._data = data
+ if not data: self._data = {}
+ if isinstance(data, list):
+ self.importArrayData(list)
-def __makeGetData(cls):
- ''' Wraps the stored data in an accessor method '''
- def get(self):
- return self.__data
- setattr(cls, 'getData', get)
+ def importArrayData(self, data):
+ ''' If an array-based object is created with an array
+ of data, cycle through and load the data '''
-def __makeSetField(cls):
- ''' Creates a generic mutator for fields by fieldname '''
- def set(self, field, value):
- self.__data[field] = value
- setattr(cls, 'setField', set)
-
+ self._data = {}
+ if len(data) == 0: return
-def __osrfNetworkObjectInit(self, data={}):
- ''' __init__ method for osrNetworkObjects.
- If this is an array, we pull data out of the data array
- (if there is any) and translate that into a hash internally
- '''
- self.__data = data
- if isinstance(data, list) and len(data) > 0:
reg = self.getRegistry()
if reg.wireProtocol == 'array':
- self.__data = {}
for i in range(len(reg.keys)):
- try:
- self.__data[reg.keys[i]] = data[i]
- except:
- self.__data[reg.keys[i]] = None
+ if len(data) > i: break
+ self.setField(reg.keys[i], data[i])
+ def getData(self):
+ ''' Returns the full dataset for this object as a dict '''
+ return self._data
+ def setField(self, field, value):
+ self._data[field] = value
+
+ def getField(self, field):
+ return self._data.get(field)
+
+ def getRegistry(cls):
+ ''' Returns the registry object for this registered class '''
+ return cls.registry
+ getRegistry = classmethod(getRegistry)
+
+
+def osrfNewObjectFromHint(hint):
+ ''' Given a hint, this will create a new object of that
+ type and return it. If this hint is not registered,
+ an object of type osrfNetworkObject.__unknown is returned'''
+ try:
+ obj = None
+ exec('obj = osrfNetworkObject.%s()' % hint)
+ return obj
+ except AttributeError:
+ return osrfNetworkObject.__unknown()
+
+
+
+
+def __makeNetworkAccessor(cls, key):
+ ''' Creates and accessor/mutator method for the given class.
+ 'key' is the name the method will have and represents
+ the field on the object whose data we are accessing '''
+ def accessor(self, *args):
+ if len(args) != 0:
+ self.setField(key, args[0])
+ return self.getField(key)
+ setattr(cls, key, accessor)
+
+
def osrfNetworkRegisterHint(hint, keys, type='hash'):
''' Registers a new network-serializable object class.
@@ -111,16 +125,10 @@
for k in keys:
__makeNetworkAccessor(cls, k)
- # assign our custom init function
- setattr(cls, '__init__', __osrfNetworkObjectInit)
- __makeGetRegistry(cls, registry)
- __makeGetData(cls)
- __makeSetField(cls)
-
-
# attach our new class to the osrfNetworkObject
# class so others can access it
setattr(osrfNetworkObject, hint , cls)
+ cls.registry = registry
Modified: branches/autotools/src/python/osrf/ses.py
===================================================================
--- branches/autotools/src/python/osrf/ses.py 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/python/osrf/ses.py 2007-11-05 13:40:16 UTC (rev 1121)
@@ -19,7 +19,7 @@
from osrf.net import osrfNetworkMessage, osrfGetNetworkHandle
from osrf.log import *
from osrf.const import *
-import random, sys, os, time
+import random, sys, os, time, threading
# -----------------------------------------------------------------------
@@ -35,10 +35,16 @@
class osrfSession(object):
"""Abstract session superclass."""
+ ''' Global cache of in-service sessions '''
+ sessionCache = {}
+
def __init__(self):
# by default, we're connected to no one
self.state = OSRF_APP_SESSION_DISCONNECTED
+ def findSession(threadTrace):
+ return osrfSession.sessionCache.get(threadTrace)
+ findSession = staticmethod(findSession)
def wait(self, timeout=120):
"""Wait up to <timeout> seconds for data to arrive on the network"""
@@ -58,7 +64,7 @@
def cleanup(self):
"""Removes the session from the global session cache."""
- del osrfClientSession.sessionCache[self.thread]
+ del osrfSession.sessionCache[self.thread]
class osrfClientSession(osrfSession):
"""Client session object. Use this to make server requests."""
@@ -78,7 +84,8 @@
self.origRemoteId = self.remoteId
# generate a random message thread
- self.thread = "%s%s%s" % (os.getpid(), str(random.randint(100,100000)), str(time.time()))
+ self.thread = "%s%s%s%s" % (os.getpid(),
+ str(random.randint(100,100000)), str(time.time()),threading.currentThread().getName().lower())
# how many requests this session has taken part in
self.nextId = 0
@@ -87,7 +94,7 @@
self.requests = {}
# cache this session in the global session cache
- osrfClientSession.sessionCache[self.thread] = self
+ osrfSession.sessionCache[self.thread] = self
def resetRequestTimeout(self, rid):
req = self.findRequest(rid)
@@ -190,13 +197,6 @@
-osrfSession.sessionCache = {}
-def osrfFindSession(thread):
- """Finds a session in the global cache."""
- try:
- return osrfClientSession.sessionCache[thread]
- except: return None
-
class osrfRequest(object):
"""Represents a single OpenSRF request.
A request is made and any resulting respones are
Modified: branches/autotools/src/python/osrf/stack.py
===================================================================
--- branches/autotools/src/python/osrf/stack.py 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/python/osrf/stack.py 2007-11-05 13:40:16 UTC (rev 1121)
@@ -16,13 +16,13 @@
from osrf.json import *
from osrf.log import *
from osrf.ex import *
-from osrf.ses import osrfFindSession, osrfClientSession, osrfServerSession
+from osrf.ses import osrfSession, osrfClientSession, osrfServerSession
from osrf.const import *
from time import time
def osrfPushStack(netMessage):
- ses = osrfFindSession(netMessage.thread)
+ ses = osrfSession.findSession(netMessage.thread)
if not ses:
# This is an incoming request from a client, create a new server session
Modified: branches/autotools/src/python/osrf/system.py
===================================================================
--- branches/autotools/src/python/osrf/system.py 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/python/osrf/system.py 2007-11-05 13:40:16 UTC (rev 1121)
@@ -14,7 +14,7 @@
# -----------------------------------------------------------------------
from osrf.conf import osrfConfig, osrfConfigValue, osrfConfigValueNoEx
-from osrf.net import osrfNetwork, osrfSetNetworkHandle
+from osrf.net import osrfNetwork, osrfSetNetworkHandle, osrfGetNetworkHandle
from osrf.stack import osrfPushStack
from osrf.log import *
from osrf.set import osrfLoadSettings
@@ -24,6 +24,10 @@
def osrfConnect(configFile, configContext):
""" Connects to the opensrf network """
+ if osrfGetNetworkHandle():
+ ''' This thread already has a handle '''
+ return
+
# parse the config file
configParser = osrfConfig(configFile, configContext)
configParser.parseConfig()
@@ -49,3 +53,5 @@
+
+
Modified: branches/autotools/src/python/srfsh.py
===================================================================
--- branches/autotools/src/python/srfsh.py 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/python/srfsh.py 2007-11-05 13:40:16 UTC (rev 1121)
@@ -11,73 +11,73 @@
# main listen loop
# -------------------------------------------------------------------
def do_loop():
- while True:
+ while True:
- try:
- #line = raw_input("srfsh% ")
- line = raw_input("\033[01;32msrfsh\033[01;34m% \033[00m")
- if not len(line):
- continue
- if lower(line) == 'exit' or lower(line) == 'quit':
- break
- parts = split(line)
+ try:
+ #line = raw_input("srfsh% ")
+ line = raw_input("\033[01;32msrfsh\033[01;34m% \033[00m")
+ if not len(line):
+ continue
+ if lower(line) == 'exit' or lower(line) == 'quit':
+ break
+ parts = split(line)
- command = parts[0]
-
- if command == 'request':
- parts.pop(0)
- handle_request(parts)
- continue
+ command = parts[0]
+
+ if command == 'request':
+ parts.pop(0)
+ handle_request(parts)
+ continue
- if command == 'math_bench':
- parts.pop(0)
- handle_math_bench(parts)
- continue
+ if command == 'math_bench':
+ parts.pop(0)
+ handle_math_bench(parts)
+ continue
- if command == 'help':
- handle_help()
- continue
+ if command == 'help':
+ handle_help()
+ continue
- if command == 'set':
- parts.pop(0)
- handle_set(parts)
+ if command == 'set':
+ parts.pop(0)
+ handle_set(parts)
- if command == 'get':
- parts.pop(0)
- handle_get(parts)
+ if command == 'get':
+ parts.pop(0)
+ handle_get(parts)
- except KeyboardInterrupt:
- print ""
+ except KeyboardInterrupt:
+ print ""
- except EOFError:
- print "exiting..."
- sys.exit(0)
+ except EOFError:
+ print "exiting..."
+ sys.exit(0)
# -------------------------------------------------------------------
# Set env variables to control behavior
# -------------------------------------------------------------------
def handle_set(parts):
- m = re.compile('(.*)=(.*)').match(parts[0])
- key = m.group(1)
- val = m.group(2)
- set_var(key, val)
- print "%s = %s" % (key, val)
+ m = re.compile('(.*)=(.*)').match(parts[0])
+ key = m.group(1)
+ val = m.group(2)
+ set_var(key, val)
+ print "%s = %s" % (key, val)
def handle_get(parts):
- try:
- print get_var(parts[0])
- except:
- print ""
+ try:
+ print get_var(parts[0])
+ except:
+ print ""
# -------------------------------------------------------------------
# Prints help info
# -------------------------------------------------------------------
def handle_help():
- print """
+ print """
help
- show this menu
@@ -93,88 +93,88 @@
Environment variables:
SRFSH_OUTPUT = pretty - print pretty JSON and key/value pairs for network objects
= raw - print formatted JSON
- """
+ """
-
+
# -------------------------------------------------------------------
# performs an opesnrf request
# -------------------------------------------------------------------
def handle_request(parts):
- service = parts.pop(0)
- method = parts.pop(0)
- jstr = '[%s]' % join(parts)
- params = None
+ service = parts.pop(0)
+ method = parts.pop(0)
+ jstr = '[%s]' % join(parts)
+ params = None
- try:
- params = osrfJSONToObject(jstr)
- except:
- print "Error parsing JSON: %s" % jstr
- return
+ try:
+ params = osrfJSONToObject(jstr)
+ except:
+ print "Error parsing JSON: %s" % jstr
+ return
- ses = osrfClientSession(service)
+ ses = osrfClientSession(service)
- end = None
- start = time.time()
+ end = None
+ start = time.time()
- req = ses.request2(method, tuple(params))
+ req = ses.request2(method, tuple(params))
- while True:
- resp = req.recv(timeout=120)
- if not end:
- total = time.time() - start
- if not resp: break
+ while True:
+ resp = req.recv(timeout=120)
+ if not end:
+ total = time.time() - start
+ if not resp: break
- otp = get_var('SRFSH_OUTPUT')
- if otp == 'pretty':
- print osrfDebugNetworkObject(resp.content())
- else:
- print osrfFormatJSON(osrfObjectToJSON(resp.content()))
+ otp = get_var('SRFSH_OUTPUT')
+ if otp == 'pretty':
+ print "\n" + osrfDebugNetworkObject(resp.content())
+ else:
+ print osrfFormatJSON(osrfObjectToJSON(resp.content()))
- req.cleanup()
- ses.cleanup()
+ req.cleanup()
+ ses.cleanup()
- print '-'*60
- print "Total request time: %f" % total
- print '-'*60
+ print '-'*60
+ print "Total request time: %f" % total
+ print '-'*60
def handle_math_bench(parts):
- count = int(parts.pop(0))
- ses = osrfClientSession('opensrf.math')
- times = []
+ count = int(parts.pop(0))
+ ses = osrfClientSession('opensrf.math')
+ times = []
- for i in range(100):
- if i % 10: sys.stdout.write('.')
- else: sys.stdout.write( str( i / 10 ) )
- print "";
+ for i in range(100):
+ if i % 10: sys.stdout.write('.')
+ else: sys.stdout.write( str( i / 10 ) )
+ print "";
- for i in range(count):
-
- starttime = time.time()
- req = ses.request('add', 1, 2)
- resp = req.recv(timeout=2)
- endtime = time.time()
-
- if resp.content() == 3:
- sys.stdout.write("+")
- sys.stdout.flush()
- times.append( endtime - starttime )
- else:
- print "What happened? %s" % str(resp.content())
-
- req.cleanup()
- if not ( (i+1) % 100):
- print ' [%d]' % (i+1)
-
- ses.cleanup()
- total = 0
- for i in times: total += i
- print "\naverage time %f" % (total / len(times))
+ for i in range(count):
+
+ starttime = time.time()
+ req = ses.request('add', 1, 2)
+ resp = req.recv(timeout=2)
+ endtime = time.time()
+
+ if resp.content() == 3:
+ sys.stdout.write("+")
+ sys.stdout.flush()
+ times.append( endtime - starttime )
+ else:
+ print "What happened? %s" % str(resp.content())
+
+ req.cleanup()
+ if not ( (i+1) % 100):
+ print ' [%d]' % (i+1)
+
+ ses.cleanup()
+ total = 0
+ for i in times: total += i
+ print "\naverage time %f" % (total / len(times))
@@ -183,87 +183,87 @@
# Defines the tab-completion handling and sets up the readline history
# -------------------------------------------------------------------
def setup_readline():
- class SrfshCompleter(object):
- def __init__(self, words):
- self.words = words
- self.prefix = None
-
- def complete(self, prefix, index):
- if prefix != self.prefix:
- # find all words that start with this prefix
- self.matching_words = [
- w for w in self.words if w.startswith(prefix)
- ]
- self.prefix = prefix
- try:
- return self.matching_words[index]
- except IndexError:
- return None
-
- words = 'request', 'help', 'exit', 'quit', 'opensrf.settings', 'opensrf.math', 'set'
- completer = SrfshCompleter(words)
- readline.parse_and_bind("tab: complete")
- readline.set_completer(completer.complete)
+ class SrfshCompleter(object):
+ def __init__(self, words):
+ self.words = words
+ self.prefix = None
+
+ def complete(self, prefix, index):
+ if prefix != self.prefix:
+ # find all words that start with this prefix
+ self.matching_words = [
+ w for w in self.words if w.startswith(prefix)
+ ]
+ self.prefix = prefix
+ try:
+ return self.matching_words[index]
+ except IndexError:
+ return None
+
+ words = 'request', 'help', 'exit', 'quit', 'opensrf.settings', 'opensrf.math', 'set'
+ completer = SrfshCompleter(words)
+ readline.parse_and_bind("tab: complete")
+ readline.set_completer(completer.complete)
- histfile = os.path.join(get_var('HOME'), ".srfsh_history")
- try:
- readline.read_history_file(histfile)
- except IOError:
- pass
- atexit.register(readline.write_history_file, histfile)
+ histfile = os.path.join(get_var('HOME'), ".srfsh_history")
+ try:
+ readline.read_history_file(histfile)
+ except IOError:
+ pass
+ atexit.register(readline.write_history_file, histfile)
def do_connect():
- file = os.path.join(get_var('HOME'), ".srfsh.xml")
- print_green("Connecting to opensrf...")
- osrfConnect(file, 'srfsh')
- print_red('OK\n')
+ file = os.path.join(get_var('HOME'), ".srfsh.xml")
+ print_green("Connecting to opensrf...")
+ osrfConnect(file, 'srfsh')
+ print_red('OK\n')
def load_plugins():
- # Load the user defined external plugins
- # XXX Make this a real module interface, with tab-complete words, commands, etc.
- plugins = osrfConfigValue('plugins')
- plugins = osrfConfigValue('plugins.plugin')
- if not isinstance(plugins, list):
- plugins = [plugins]
+ # Load the user defined external plugins
+ # XXX Make this a real module interface, with tab-complete words, commands, etc.
+ plugins = osrfConfigValue('plugins')
+ plugins = osrfConfigValue('plugins.plugin')
+ if not isinstance(plugins, list):
+ plugins = [plugins]
- for module in plugins:
- name = module['module']
- init = module['init']
- print_green("Loading module %s..." % name)
+ for module in plugins:
+ name = module['module']
+ init = module['init']
+ print_green("Loading module %s..." % name)
- try:
- str = 'from %s import %s\n%s()' % (name, init, init)
- exec(str)
- print_red('OK\n')
+ try:
+ str = 'from %s import %s\n%s()' % (name, init, init)
+ exec(str)
+ print_red('OK\n')
- except Exception, e:
- sys.stderr.write("\nError importing plugin %s, with init symbol %s: \n%s\n" % (name, init, e))
+ except Exception, e:
+ sys.stderr.write("\nError importing plugin %s, with init symbol %s: \n%s\n" % (name, init, e))
def set_vars():
- if not get_var('SRFSH_OUTPUT'):
- set_var('SRFSH_OUTPUT', 'pretty')
+ if not get_var('SRFSH_OUTPUT'):
+ set_var('SRFSH_OUTPUT', 'pretty')
def set_var(key, val):
- os.environ[key] = val
+ os.environ[key] = val
def get_var(key):
- try: return os.environ[key]
- except: return ''
-
-
+ try: return os.environ[key]
+ except: return ''
+
+
def print_green(str):
- sys.stdout.write("\033[01;32m")
- sys.stdout.write(str)
- sys.stdout.write("\033[00m")
- sys.stdout.flush()
+ sys.stdout.write("\033[01;32m")
+ sys.stdout.write(str)
+ sys.stdout.write("\033[00m")
+ sys.stdout.flush()
def print_red(str):
- sys.stdout.write("\033[01;31m")
- sys.stdout.write(str)
- sys.stdout.write("\033[00m")
- sys.stdout.flush()
+ sys.stdout.write("\033[01;31m")
+ sys.stdout.write(str)
+ sys.stdout.write("\033[00m")
+ sys.stdout.flush()
Modified: branches/autotools/src/router/Makefile
===================================================================
--- branches/autotools/src/router/Makefile 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/router/Makefile 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,6 +1,6 @@
#MALLOC_CHECK_=1 # XXX debug only
-LDLIBS += -lxml2 -lopensrf -lobjson
+LDLIBS += -lxml2 -lopensrf
CFLAGS += -D_ROUTER
all: opensrf_router
Modified: branches/autotools/src/router/osrf_router.c
===================================================================
--- branches/autotools/src/router/osrf_router.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/router/osrf_router.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -119,7 +119,7 @@
/* if the sender is not a trusted server, drop the message */
int len = strlen(msg->sender) + 1;
char domain[len];
- bzero(domain, len);
+ memset(domain, 0, sizeof(domain));
jid_get_domain( msg->sender, domain, len - 1 );
if(osrfStringArrayContains( router->trustedServers, domain))
@@ -150,7 +150,7 @@
/* if the client is not from a trusted domain, drop the message */
int len = strlen(msg->sender) + 1;
char domain[len];
- bzero(domain, len);
+ memset(domain, 0, sizeof(domain));
jid_get_domain( msg->sender, domain, len - 1 );
if(osrfStringArrayContains( router->trustedClients, domain)) {
@@ -486,7 +486,7 @@
int T = 32;
osrfMessage* arr[T];
- memset(arr, 0, T );
+ memset(arr, 0, sizeof(arr));
int num_msgs = osrf_message_deserialize( msg->body, arr, T );
osrfMessage* omsg = NULL;
@@ -520,7 +520,7 @@
osrfMessage* success = osrf_message_init( STATUS, omsg->thread_trace, omsg->protocol );
- osrfLogDebug( OSRF_LOG_MARK, "router recevied a CONNECT message from %s", msg->sender );
+ osrfLogDebug( OSRF_LOG_MARK, "router received a CONNECT message from %s", msg->sender );
osrf_message_set_status_info(
success, "osrfConnectStatus", "Connection Successful", OSRF_STATUS_OK );
Modified: branches/autotools/src/srfsh/Makefile
===================================================================
--- branches/autotools/src/srfsh/Makefile 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/srfsh/Makefile 2007-11-05 13:40:16 UTC (rev 1121)
@@ -1,6 +1,6 @@
# if EXEC_DEFAULT is defined, then srfsh will send all unknown commands to the shell for execution
-LDLIBS += -lobjson -lreadline -lxml2 -lopensrf -lncurses
+LDLIBS += -lreadline -lxml2 -lopensrf -lncurses
LDFLAGS += -DEXEC_DEFAULT
all: srfsh
Modified: branches/autotools/src/srfsh/srfsh.c
===================================================================
--- branches/autotools/src/srfsh/srfsh.c 2007-11-04 11:38:50 UTC (rev 1120)
+++ branches/autotools/src/srfsh/srfsh.c 2007-11-05 13:40:16 UTC (rev 1121)
@@ -47,7 +47,7 @@
static int handle_router( char* words[] );
/* utility method for print time data */
-/* static int handle_time( char* words[] ); */
+static int handle_time( char* words[] );
/* handles app level requests */
static int handle_request( char* words[], int relay );
@@ -80,8 +80,7 @@
char* home = getenv("HOME");
int l = strlen(home) + 36;
char fbuf[l];
- memset(fbuf, 0, l);
- sprintf(fbuf,"%s/.srfsh.xml",home);
+ snprintf(fbuf, sizeof(fbuf), "%s/.srfsh.xml", home);
if(!access(fbuf, R_OK)) {
if( ! osrf_system_bootstrap_client(fbuf, "srfsh") ) {
@@ -182,33 +181,18 @@
write_history(history_file);
free(request);
+ free(login_session);
osrf_system_shutdown();
return 0;
}
-/*
-static void sig_child_handler( int s ) {
- child_dead = 1;
-}
-*/
-
-/*
-void sig_int_handler( int s ) {
- printf("\n");
- caught_sigint = 1;
- signal(SIGINT,sig_int_handler);
-}
-*/
-
static int load_history( void ) {
char* home = getenv("HOME");
int l = strlen(home) + 24;
char fbuf[l];
-
- memset(fbuf, 0, l);
- sprintf(fbuf,"%s/.srfsh_history",home);
+ snprintf(fbuf, sizeof(fbuf), "%s/.srfsh_history", home);
history_file = strdup(fbuf);
if(!access(history_file, W_OK | R_OK )) {
@@ -279,10 +263,8 @@
if( !strcmp(words[0],"router") )
ret_val = handle_router( words );
- /*
else if( !strcmp(words[0],"time") )
ret_val = handle_time( words );
- */
else if (!strcmp(words[0],"request"))
ret_val = handle_request( words, 0 );
@@ -337,14 +319,14 @@
static const char text[] = "request %s opensrf.system.method %s";
len = sizeof( text ) + strlen( words[1] ) + strlen( words[2] );
char buf[len];
- sprintf( buf, text, words[1], words[2] );
+ snprintf( buf, sizeof(buf), text, words[1], words[2] );
return parse_request( buf );
} else {
static const char text[] = "request %s opensrf.system.method.all";
len = sizeof( text ) + strlen( words[1] );
char buf[len];
- sprintf( buf, text, words[1] );
+ snprintf( buf, sizeof(buf), text, words[1] );
return parse_request( buf );
}
@@ -363,17 +345,14 @@
int orgloci = (orgloc) ? atoi(orgloc) : 0;
if(!type) type = "opac";
- char buf[256];
- memset(buf,0,256);
+ char login_text[] = "request open-ils.auth open-ils.auth.authenticate.init \"%s\"";
+ size_t len = sizeof( login_text ) + strlen(username) + 1;
- char buf2[256];
- memset(buf2,0,256);
+ char buf[len];
+ snprintf( buf, sizeof(buf), login_text, username );
+ parse_request(buf);
- sprintf( buf,
- "request open-ils.auth open-ils.auth.authenticate.init \"%s\"", username );
- parse_request(buf);
-
- char* hash;
+ const char* hash;
if(last_result && last_result->_result_content) {
jsonObject* r = last_result->_result_content;
hash = jsonObjectGetString(r);
@@ -382,19 +361,12 @@
char* pass_buf = md5sum(password);
- char both_buf[256];
- memset(both_buf,0,256);
- sprintf(both_buf,"%s%s",hash, pass_buf);
+ size_t both_len = strlen( hash ) + strlen( pass_buf ) + 1;
+ char both_buf[both_len];
+ snprintf(both_buf, sizeof(both_buf), "%s%s", hash, pass_buf);
char* mess_buf = md5sum(both_buf);
- /*
- sprintf( buf2, "request open-ils.auth open-ils.auth.authenticate.complete "
- "{ \"username\" : \"%s\", \"password\" : \"%s\", "
- "\"type\" : \"%s\", \"org\" : %d, \"workstation\": \"%s\"}",
- username, mess_buf, type, orgloci, workstation );
- */
-
growing_buffer* argbuf = buffer_init(64);
buffer_fadd(argbuf,
"request open-ils.auth open-ils.auth.authenticate.complete "
@@ -411,19 +383,26 @@
parse_request( argbuf->buf );
buffer_free(argbuf);
- jsonObject* x = last_result->_result_content;
+ if( login_session != NULL )
+ free( login_session );
+
+ const jsonObject* x = last_result->_result_content;
double authtime = 0;
if(x) {
- char* authtoken = jsonObjectGetString(
- jsonObjectGetKey(jsonObjectGetKey(x,"payload"), "authtoken"));
+ const char* authtoken = jsonObjectGetString(
+ jsonObjectGetKeyConst(jsonObjectGetKeyConst(x,"payload"), "authtoken"));
authtime = jsonObjectGetNumber(
- jsonObjectGetKey(jsonObjectGetKey(x,"payload"), "authtime"));
- if(authtoken) login_session = strdup(authtoken);
- else login_session = NULL;
+ jsonObjectGetKeyConst(jsonObjectGetKeyConst(x,"payload"), "authtime"));
+
+ if(authtoken)
+ login_session = strdup(authtoken);
+ else
+ login_session = NULL;
}
else login_session = NULL;
- printf("Login Session: %s. Session timeout: %f\n", login_session, authtime );
+ printf("Login Session: %s. Session timeout: %f\n",
+ (login_session ? login_session : "(none)"), authtime );
return 1;
@@ -487,8 +466,19 @@
}
}
+ if(!strcmp(variable,"raw_print")) {
+ if(raw_print) {
+ printf("raw_print = true\n");
+ return 1;
+ } else {
+ printf("raw_print = false\n");
+ return 1;
+ }
+ }
+
if(!strcmp(variable,"login")) {
- printf("login session = %s\n", login_session );
+ printf("login session = %s\n",
+ login_session ? login_session : "(none)" );
return 1;
}
@@ -558,7 +548,7 @@
jsonObject* params = NULL;
if( !relay ) {
if( buffer != NULL && buffer->n_used > 0 )
- params = json_parse_string(buffer->buf);
+ params = jsonParseString(buffer->buf);
} else {
if(!last_result || ! last_result->_result_content) {
printf("We're not going to call 'relay' with no result params\n");
@@ -616,22 +606,25 @@
char* content;
- if( pretty_print && omsg->_result_content ) {
+ if( pretty_print ) {
char* j = jsonObjectToJSON(omsg->_result_content);
//content = json_printer(j);
content = jsonFormatString(j);
free(j);
- } else
- content = jsonObjectGetString(omsg->_result_content);
-
+ } else {
+ const char * temp_content = jsonObjectGetString(omsg->_result_content);
+ if( ! temp_content )
+ temp_content = "[null]";
+ content = strdup( temp_content );
+ }
+
printf( "\nReceived Data: %s\n", content );
free(content);
} else {
char code[16];
- memset(code, 0, 16);
- sprintf( code, "%d", omsg->status_code );
+ snprintf( code, sizeof(code), "%d", omsg->status_code );
buffer_add( resp_buffer, code );
printf( "\nReceived Exception:\nName: %s\nStatus: %s\nStatus: %s\n",
@@ -654,9 +647,14 @@
//content = json_printer(j);
content = jsonFormatString(j);
free(j);
- } else
- content = jsonObjectGetString(omsg->_result_content);
-
+ } else {
+ const char * temp_content = jsonObjectGetString(omsg->_result_content);
+ if( temp_content )
+ content = strdup( temp_content );
+ else
+ content = NULL;
+ }
+
buffer_add( resp_buffer, "\nReceived Data: " );
buffer_add( resp_buffer, content );
buffer_add( resp_buffer, "\n" );
@@ -670,8 +668,7 @@
buffer_add( resp_buffer, omsg->status_text );
buffer_add( resp_buffer, "\nStatus: " );
char code[16];
- memset(code, 0, 16);
- sprintf( code, "%d", omsg->status_code );
+ snprintf( code, sizeof(code), "%d", omsg->status_code );
buffer_add( resp_buffer, code );
}
}
@@ -705,30 +702,15 @@
}
-/*
static int handle_time( char* words[] ) {
-
- if( ! words[1] ) {
-
- char buf[36];
- memset(buf,0,36);
- get_timestamp(buf);
- printf( "%s\n", buf );
- return 1;
- }
-
- if( words[1] ) {
- time_t epoch = (time_t)atoi( words[1] );
- char* localtime = strdup( ctime( &epoch ) );
- printf( "%s => %s", words[1], localtime );
- free(localtime);
- return 1;
- }
-
- return 0;
-
+ if(!words[1]) {
+ printf("%f\n", get_timestamp_millis());
+ } else {
+ time_t epoch = (time_t) atoi(words[1]);
+ printf("%s", ctime(&epoch));
+ }
+ return 1;
}
-*/
@@ -737,9 +719,10 @@
if( ! router_server || strlen(router_server) == 0 )
return 0;
- char rbuf[256];
- memset(rbuf,0,256);
- sprintf(rbuf,"router@%s/router", router_server );
+ const static char router_text[] = "router@%s/router";
+ size_t len = sizeof( router_text ) + strlen( router_server ) + 1;
+ char rbuf[len];
+ snprintf(rbuf, sizeof(rbuf), router_text, router_server );
transport_message* send =
message_init( "servers", NULL, NULL, rbuf, NULL );
@@ -775,47 +758,47 @@
"---------------------------------------------------------------------------------\n"
"Commands:\n"
"---------------------------------------------------------------------------------\n"
- "help - Display this message\n"
- "!<command> [args] - Forks and runs the given command in the shell\n"
+ "help - Display this message\n"
+ "!<command> [args] - Forks and runs the given command in the shell\n"
/*
"time - Prints the current time\n"
- "time <timestamp> - Formats seconds since epoch into readable format\n"
+ "time <timestamp> - Formats seconds since epoch into readable format\n"
*/
"set <variable> <value> - set a srfsh variable (e.g. set pretty_print true )\n"
- "print <variable> - Displays the value of a srfsh variable\n"
+ "print <variable> - Displays the value of a srfsh variable\n"
"---------------------------------------------------------------------------------\n"
"router query servers <server1 [, server2, ...]>\n"
- " - Returns stats on connected services\n"
+ " - Returns stats on connected services\n"
"\n"
"\n"
"request <service> <method> [ <json formatted string of params> ]\n"
- " - Anything passed in will be wrapped in a json array,\n"
- " so add commas if there is more than one param\n"
+ " - Anything passed in will be wrapped in a json array,\n"
+ " so add commas if there is more than one param\n"
"\n"
"\n"
"relay <service> <method>\n"
- " - Performs the requested query using the last received result as the param\n"
+ " - Performs the requested query using the last received result as the param\n"
"\n"
"\n"
"math_bench <num_batches> [0|1|2]\n"
- " - 0 means don't reconnect, 1 means reconnect after each batch of 4, and\n"
- " 2 means reconnect after every request\n"
+ " - 0 means don't reconnect, 1 means reconnect after each batch of 4, and\n"
+ " 2 means reconnect after every request\n"
"\n"
"introspect <service>\n"
- " - prints the API for the service\n"
+ " - prints the API for the service\n"
"\n"
"\n"
"---------------------------------------------------------------------------------\n"
" Commands for Open-ILS\n"
"---------------------------------------------------------------------------------\n"
"login <username> <password>\n"
- " - Logs into the 'server' and displays the session id\n"
- " - To view the session id later, enter: print login\n"
+ " - Logs into the 'server' and displays the session id\n"
+ " - To view the session id later, enter: print login\n"
"---------------------------------------------------------------------------------\n"
"\n"
"\n"
- "Note: long output is piped through 'less'. To search in 'less', type: /<search>\n"
+ "Note: long output is piped through 'less'. To search in 'less', type: /<search>\n"
"---------------------------------------------------------------------------------\n"
"\n"
);
@@ -850,7 +833,7 @@
osrf_app_session* session = osrf_app_client_session_init( "opensrf.math" );
osrf_app_session_connect(session);
- jsonObject* params = json_parse_string("[]");
+ jsonObject* params = jsonParseString("[]");
jsonObjectPush(params,jsonNewObject("1"));
jsonObjectPush(params,jsonNewObject("2"));
@@ -858,7 +841,7 @@
char* answers[] = { "3", "-1", "2", "0.500000" };
float times[ count * 4 ];
- memset(times,0,count*4);
+ memset(times, 0, sizeof(times));
int k;
for(k=0;k!=100;k++) {
More information about the opensrf-commits
mailing list