[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 $(T