Merged revisions 984-1044 via svnmerge.
authorasmodai <asmodai@9efc2488-bf62-4759-914b-345cdb29e865>
Wed, 18 Jul 2007 05:21:54 +0000 (05:21 +0000)
committerasmodai <asmodai@9efc2488-bf62-4759-914b-345cdb29e865>
Wed, 18 Jul 2007 05:21:54 +0000 (05:21 +0000)
git-svn-id: svn://svn.open-ils.org/OpenSRF/branches/autotools@1045 9efc2488-bf62-4759-914b-345cdb29e865

63 files changed:
COPYING [new file with mode: 0644]
LICENSE.txt [new file with mode: 0644]
bin/osrf_ctl.sh
doc/dokuwiki-doc-stubber.pl
examples/bootstrap.conf.example [deleted file]
examples/fieldmapper2perl.xsl
examples/math_bench.pl
examples/multisession-test.pl
examples/opensrf.xml.example
examples/opensrf_core.xml.example
examples/srfsh.xml.example
include/objson/json_parser.h
include/opensrf/socket_bundle.h
src/Makefile
src/jserver/osrf_chat.c
src/libopensrf/opensrf.c
src/libopensrf/osrf_prefork.c
src/libopensrf/osrf_system.c
src/libopensrf/socket_bundle.c
src/libopensrf/transport_message.c
src/libopensrf/transport_session.c
src/libopensrf/utils.c
src/libopensrf/xml_utils.c
src/objson/json_parser.c
src/perlmods/JSON.pm [deleted file]
src/perlmods/OpenSRF/AppSession.pm
src/perlmods/OpenSRF/Application.pm
src/perlmods/OpenSRF/Application/Demo/Math.pm
src/perlmods/OpenSRF/Application/Demo/MathDB.pm
src/perlmods/OpenSRF/Application/Persist.pm
src/perlmods/OpenSRF/DOM.pm [deleted file]
src/perlmods/OpenSRF/DOM/Element/domainObject.pm [deleted file]
src/perlmods/OpenSRF/DOM/Element/domainObjectAttr.pm [deleted file]
src/perlmods/OpenSRF/DOM/Element/domainObjectCollection.pm [deleted file]
src/perlmods/OpenSRF/DOM/Element/params.pm [deleted file]
src/perlmods/OpenSRF/DomainObject.pm [deleted file]
src/perlmods/OpenSRF/DomainObject/oilsMessage.pm
src/perlmods/OpenSRF/DomainObject/oilsMethod.pm
src/perlmods/OpenSRF/DomainObject/oilsMultiSearch.pm [deleted file]
src/perlmods/OpenSRF/DomainObject/oilsPrimitive.pm [deleted file]
src/perlmods/OpenSRF/DomainObject/oilsResponse.pm
src/perlmods/OpenSRF/DomainObject/oilsSearch.pm [deleted file]
src/perlmods/OpenSRF/DomainObjectCollection.pm [deleted file]
src/perlmods/OpenSRF/EX.pm
src/perlmods/OpenSRF/System.pm
src/perlmods/OpenSRF/Transport.pm
src/perlmods/OpenSRF/UnixServer.pm
src/perlmods/OpenSRF/Utils/Cache.pm
src/perlmods/OpenSRF/Utils/JSON.pm [new file with mode: 0644]
src/perlmods/OpenSRF/Utils/Logger.pm
src/python/osrf/conf.py
src/python/osrf/gateway.py
src/python/osrf/json.py
src/python/osrf/log.py
src/python/osrf/net_obj.py
src/python/osrf/ses.py
src/python/osrf/system.py
src/python/osrf/utils.py
src/python/srfsh.py
src/router/osrf_router_main.c
src/srfsh/Makefile
src/srfsh/srfsh.c
src/srfsh/srfsh.h [deleted file]

diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..6235a64
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,17 @@
+ Copyright (C) 2005-2007, Georgia Public Library Service and others
+
+ 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.
+
+ You should have received a copy of the GNU General Public 
+ License along with this program; if not, write to the Free 
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ MA 02111-1307 USA
+
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644 (file)
index 0000000..113c29b
--- /dev/null
@@ -0,0 +1,340 @@
+GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
index 374385d..8958204 100755 (executable)
@@ -119,9 +119,9 @@ function stop_router {
 function start_perl {
        do_action "start" $PID_OSRF_PERL "OpenSRF Perl";
        perl -MOpenSRF::System="$OPT_CONFIG" -e 'OpenSRF::System->bootstrap()' & 
-       pid=$!;
+       sleep 3;
+       pid=$(ps ax | grep "OpenSRF System" | grep -v grep | grep -v "System-C"| awk '{print $1}')
        echo $pid > $PID_OSRF_PERL;
-       sleep 5;
        return 0;
 }
 
index fcdd03d..0182745 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-use OpenSRF::System qw(/pines/conf/bootstrap.conf);
+use OpenSRF::System qw(/openils/conf/opensrf_core.xml);
 use Getopt::Long
 
 $| = 1;
diff --git a/examples/bootstrap.conf.example b/examples/bootstrap.conf.example
deleted file mode 100644 (file)
index ce445f7..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# ----------------------------------------------------------
-# bootstrap config file
-# ----------------------------------------------------------
-[bootstrap]
-
-# location of the opensrf.xml config file
-settings_config        = /path/to/opensrf.xml
-
-# log files directory
-log_dir                                = /path/to/log
-
-## Log file is either a file name or syslog:<facility> 
-#logfile                               = osrfysys.log
-logfile                                = syslog:local0
-
-# defines the syslog facility for the activity log
-#actlog                                = activity.log
-actlog                         = syslog:local1
-
-# log level
-debug                                  = ERROR
-#debug                         = INFO
-#debug                         = DEBUG
-#debug                         = INTERNAL
-
-# the jabber login of the router (changing this will likely cause problems)
-router_name                    = router
-
-# all jabber domains we want our app to connect to
-list:domains           = router1.domain.com, router2.domain.com
-
-# jabber login
-username                               = jabber_username
-
-# jabber password
-passwd                         = jabber_password
-
-# if port is non-numeric (e.g. /tmp/mysock.sock) then we will attempt to
-# connect to the specified string as a unix socket file 
-# This works with Chop Chop jabber only (opensrf custom jabber server)
-port                                   = 5222
-
-# --------------------------------------
-
index 4d3a8a5..8ef601e 100644 (file)
@@ -13,7 +13,7 @@
 
        <xsl:template match="/">
 package Fieldmapper;
-use JSON;
+use OpenSRF::Utils::JSON;
 use Data::Dumper;
 use base 'OpenSRF::Application';
 
index c3a504c..f83e0fc 100755 (executable)
@@ -13,7 +13,7 @@ my $count = $ARGV[0];
 print "usage: $0 <num_requests>\n" and exit unless $count;
 
 # * connect to the Jabber network
-OpenSRF::System->bootstrap_client( config_file => "/openils/conf/bootstrap.conf" );
+OpenSRF::System->bootstrap_client( config_file => "/openils/conf/opensrf_core.xml" );
 $log->set_service('math_bench');
 
 # * create a new application session for the opensrf.math service
index bb75a46..21c0c99 100755 (executable)
@@ -4,7 +4,7 @@ use OpenSRF::System;
 use OpenILS::Application::AppUtils;
 use OpenILS::Event;
 use OpenSRF::EX qw/:try/;
-use JSON;
+use OpenSRF::Utils::JSON;
 use Data::Dumper;
 use OpenILS::Utils::Fieldmapper;
 use Digest::MD5 qw/md5_hex/;
@@ -12,7 +12,6 @@ use OpenSRF::Utils qw/:daemon/;
 use OpenSRF::MultiSession;
 use OpenSRF::AppSession;
 use Time::HiRes qw/time/;
-use JSON;
 
 my $config = shift;
 
@@ -37,7 +36,7 @@ $mses->success_handler(
        sub {
                my $ses = shift;
                my $req = shift;
-               print $req->{params}->[0] . "\t: " . JSON->perl2JSON($req->{response}->[0]->content)."\n";
+               print $req->{params}->[0] . "\t: " . OpenSRF::Utils::JSON->perl2JSON($req->{response}->[0]->content)."\n";
        }
 );
 
@@ -45,7 +44,7 @@ $mses->failure_handler(
        sub {
                my $ses = shift;
                my $req = shift;
-               warn "record $req->{params}->[0] failed: ".JSON->perl2JSON($req->{response});
+               warn "record $req->{params}->[0] failed: " . OpenSRF::Utils::JSON->perl2JSON($req->{response});
        }
 );
 
index 437570a..fa2bc44 100644 (file)
-<?xml version='1.0'?>
+<?xml version="1.0"?>
+<opensrf version="0.0.1">
+<!-- 
 
-<opensrf version='0.0.1'>
+       There is one <host> entry for each server on the network.  Settings for the
+       'default' host are used for every setting that isn't overridden within a given 
+       host's config.  
 
-               <!-- 
+       To specify which applications a host is serving, list those applications
+       within that host's config section.  If the defaults are acceptible, then
+       that's all that needs to be added/changed.
 
-               There is one <host> entry for each server on the network.  Settings for the
-               'default' host are used for every setting that isn't overridden within a given 
-               host's config.  
+       Any valid XML may be added to the <default> block and server components will have 
+       acces to it.
 
-               To specify which applications a host is serving, list those applications
-               within that host's config section.  If the defaults are acceptible, then
-               that's all that needs to be added/changed.
+-->
 
-               Any valid XML may be added to the <default> block and server components will have 
-               acces to it.
+  <default>
+    <dirs>
 
-               -->
+      <!-- opensrf log files go in this directory -->
+      <log>/path/to/log</log>
 
-       <default>
-       
-               <dirs>
+      <!-- opensrf unix domaind socket files go here -->
+      <sock>/path/to/sock</sock>
 
-                       <!-- opensrf log files go in this directory -->
-                       <log>/path/to/log</log>
+      <!-- opensrf pids go here -->
+      <pid>/path/to/pid</pid>
 
-                       <!-- opensrf unix domaind socket files go here -->
-                       <sock>/path/to/sock</sock>
+      <!-- global config directory -->
+      <conf>/path/to/conf</conf>
+    </dirs>
 
-                       <!-- opensrf pids go here -->
-                       <pid>/path/to/pid</pid>
+    <!-- prefork, simple. prefork is suggested -->
+    <server_type>prefork</server_type>
 
-                       <!-- global config directory -->
-                       <conf>/path/to/conf</conf>
+    <!-- Default doesn't host any apps -->
+    <activeapps/>
+    <cache>
+      <global>
+        <servers>
 
-               </dirs>
+          <!-- memcached server ip:port -->
+          <server>127.0.0.1:10101</server>
 
-               <!-- prefork, simple. prefork is suggested -->
-               <server_type>prefork</server_type>
+        </servers>
 
-               <!-- Default doesn't host any apps -->
-               <activeapps/> 
+        <!-- maximun time that anything may stay in the cache -->
+        <max_cache_time>86400</max_cache_time>
 
-               <cache>
-                       <global>
-                               <servers>
-                                       <!-- memcached server ip:port -->
-                                       <server>127.0.0.1:10101</server>
-                               </servers>
-                               <!-- maximun time that anything may stay in the cache -->
-                               <max_cache_time>86400</max_cache_time>
-                       </global>
-               </cache>
-
-               <!-- These are the defaults for every served app.  Each server should 
-                       duplicate the node layout for any nodes that need changing.
-                       Any settings that are overridden in the server specific section 
-                       will be used as the config values for that server.  Any settings that are
-                       not overridden will fall back on the defaults
-                       Note that overriding 'stateless' will break things -->
-
-               <apps>
-
-                       <opensrf.persist>
-
-                               <!-- How many seconds to wait between server 
-                                       requests before timing out a stateful server session. -->
-                               <keepalive>1</keepalive>
-
-                               <!-- if 1, then we support stateless sessions (no connect required), if
-                                               0 then we don't -->
-                               <stateless>1</stateless>
-
-                               <!-- Tells the servers which language this implementation is coded in 
-                                       In this case non "perl" servers will not be able to load the module -->
-                               <language>perl</language>
-
-                               <!-- Module the implements this application -->
-                               <implementation>OpenSRF::Application::Persist</implementation>
-
-                               <!-- max stateful requests before a session automatically disconnects a client -->
-                               <max_requests>97</max_requests>
-
-                               <!-- settings for the backend application drones.  These are probably sane defaults -->
-
-                               <unix_config>
-                                       <!-- unix socket file -->
-                                       <unix_sock>opensrf.persist_unix.sock</unix_sock>
-
-                                       <!-- pid file -->
-                                       <unix_pid>opensrf.persist_unix.pid</unix_pid>
-
-                                       <!-- max requests per process backend before a child is recycled -->
-                                       <max_requests>1000</max_requests>
-
-                                       <!-- log file for this application -->
-                                       <unix_log>opensrf.persist_unix.log</unix_log>
-
-                                       <!-- Number of children to pre-fork -->
-                                       <min_children>5</min_children>
-
-                                       <!-- maximun number of children to fork -->
-                                       <max_children>25</max_children>
-
-                                       <!-- minimun number of spare forked children -->
-                                       <min_spare_children>2</min_spare_children>
-
-                                       <!-- max number of spare forked children -->
-                                       <max_spare_children>5</max_spare_children>
-
-                               </unix_config>
-
-                               <!-- Any additional setting for a particular application go in the app_settings node -->
-                               <app_settings>
-
-                                       <!-- sqlite database file -->
-                                       <dbfile>/path/to/dbfile/persist.db</dbfile>
-                               </app_settings>
-
-                       </opensrf.persist>
-
-                       <opensrf.math>
-                               <keepalive>3</keepalive>
-                               <stateless>1</stateless>
-                               <language>perl</language>
-                               <implementation>OpenSRF::Application::Demo::Math</implementation>
-                               <max_requests>97</max_requests>
-                               <unix_config>
-                                       <unix_sock>opensrf.math_unix.sock</unix_sock>
-                                       <unix_pid>opensrf.math_unix.pid</unix_pid>
-                                       <max_requests>1000</max_requests>
-                                       <unix_log>opensrf.math_unix.log</unix_log>
-                                       <min_children>5</min_children>
-                                       <max_children>15</max_children>
-                                       <min_spare_children>2</min_spare_children>
-                                       <max_spare_children>5</max_spare_children>
-                               </unix_config>
-                       </opensrf.math>
-                       
-                       <opensrf.dbmath> 
-                               <keepalive>3</keepalive>
-                               <stateless>1</stateless>
-                               <language>perl</language>
-                               <implementation>OpenSRF::Application::Demo::MathDB</implementation>
-                               <max_requests>99</max_requests>
-                               <unix_config>
-                                       <max_requests>1000</max_requests>
-                                       <unix_log>opensrf.dbmath_unix.log</unix_log>
-                                       <unix_sock>opensrf.dbmath_unix.sock</unix_sock>
-                                       <unix_pid>opensrf.dbmath_unix.pid</unix_pid>
-                                       <min_children>5</min_children>
-                                       <max_children>15</max_children>
-                                       <min_spare_children>2</min_spare_children> <max_spare_children>5</max_spare_children>
-                               </unix_config>
-                       </opensrf.dbmath>
-
-                       <opensrf.settings>
-                               <keepalive>1</keepalive>
-                               <stateless>0</stateless>
-                               <language>perl</language>
-                               <implementation>OpenSRF::Application::Settings</implementation>
-                               <max_requests>17</max_requests>
-                               <unix_config>
-                                       <unix_sock>opensrf.settings_unix.sock</unix_sock>
-                                       <unix_pid>opoensrf.settings_unix.pid</unix_pid>
-                                       <max_requests>1000</max_requests>
-                                       <unix_log>opensrf.settings_unix.log</unix_log>
-                                       <min_children>5</min_children>
-                                       <max_children>15</max_children>
-                                       <min_spare_children>3</min_spare_children>
-                                       <max_spare_children>5</max_spare_children>
-                               </unix_config>
-                       </opensrf.settings>
-
-               </apps>
-
-       </default>
-
-       <hosts>
-
-               <myhost.mydomain.org>
-                       <!-- ^-=-
-                               must match the fully qualified domain name of the host 
-                               on Linux, this is usually the output of "hostname -f"
-                       -->
-
-
-                       <!-- List all of the apps this server will be running -->
-                       <activeapps>
-                               <appname>opensrf.persist</appname> 
-                               <appname>opensrf.settings</appname> 
-                               <appname>opensrf.math</appname> 
-                               <appname>opensrf.dbmath</appname> 
-                       </activeapps>
-
-                       <apps> <!-- Example of an app-specific setting override -->
-                               <opensrf.persist>
-                                       <app_settings>
-                                               <dbfile>/different/path/to/dbfile/persist.db</dbfile>
-                                       </app_settings>
-                               </opensrf.persist>
-                       </apps>
-
-               </myhost.mydomain.org> 
-
-       </hosts>
+      </global>
+    </cache>
+
+<!-- These are the defaults for every served app.  Each server should 
+       duplicate the node layout for any nodes that need changing.
+       Any settings that are overridden in the server specific section 
+       will be used as the config values for that server.  Any settings that are
+       not overridden will fall back on the defaults
+       Note that overriding 'stateless' will break things -->
+
+    <apps>
+      <opensrf.persist>
+
+        <!-- How many seconds to wait between server 
+       requests before timing out a stateful server session. -->
+        <keepalive>1</keepalive>
+
+        <!-- if 1, then we support stateless sessions (no connect required),
+       if 0 then we don't -->
+        <stateless>1</stateless>
+
+        <!-- Tells the servers which language this implementation is coded in 
+       In this case non "perl" servers will not be able to load the module -->
+        <language>perl</language>
+
+        <!-- Module the implements this application -->
+        <implementation>OpenSRF::Application::Persist</implementation>
+
+        <!-- max stateful requests before a session automatically disconnects a client -->
+        <max_requests>97</max_requests>
+
+        <!-- settings for the backend application drones.  These are probably sane defaults -->
+        <unix_config>
+
+          <!-- unix socket file -->
+          <unix_sock>opensrf.persist_unix.sock</unix_sock>
+
+          <!-- pid file -->
+          <unix_pid>opensrf.persist_unix.pid</unix_pid>
+
+          <!-- max requests per process backend before a child is recycled -->
+          <max_requests>1000</max_requests>
+
+          <!-- log file for this application -->
+          <unix_log>opensrf.persist_unix.log</unix_log>
+
+          <!-- Number of children to pre-fork -->
+          <min_children>5</min_children>
+
+          <!-- maximun number of children to fork -->
+          <max_children>25</max_children>
+
+          <!-- minimun number of spare forked children -->
+          <min_spare_children>2</min_spare_children>
+
+          <!-- max number of spare forked children -->
+          <max_spare_children>5</max_spare_children>
+
+        </unix_config>
+
+        <!-- Any additional setting for a particular application go in the app_settings node -->
+        <app_settings>
+
+          <!-- sqlite database file -->
+          <dbfile>/path/to/dbfile/persist.db</dbfile>
+
+        </app_settings>
+      </opensrf.persist>
+
+      <opensrf.math>
+        <keepalive>3</keepalive>
+        <stateless>1</stateless>
+        <language>perl</language>
+        <implementation>OpenSRF::Application::Demo::Math</implementation>
+        <max_requests>97</max_requests>
+        <unix_config>
+          <unix_sock>opensrf.math_unix.sock</unix_sock>
+          <unix_pid>opensrf.math_unix.pid</unix_pid>
+          <max_requests>1000</max_requests>
+          <unix_log>opensrf.math_unix.log</unix_log>
+          <min_children>5</min_children>
+          <max_children>15</max_children>
+          <min_spare_children>2</min_spare_children>
+          <max_spare_children>5</max_spare_children>
+        </unix_config>
+      </opensrf.math>
+
+      <opensrf.dbmath>
+        <keepalive>3</keepalive>
+        <stateless>1</stateless>
+        <language>perl</language>
+        <implementation>OpenSRF::Application::Demo::MathDB</implementation>
+        <max_requests>99</max_requests>
+        <unix_config>
+          <max_requests>1000</max_requests>
+          <unix_log>opensrf.dbmath_unix.log</unix_log>
+          <unix_sock>opensrf.dbmath_unix.sock</unix_sock>
+          <unix_pid>opensrf.dbmath_unix.pid</unix_pid>
+          <min_children>5</min_children>
+          <max_children>15</max_children>
+          <min_spare_children>2</min_spare_children>
+          <max_spare_children>5</max_spare_children>
+        </unix_config>
+      </opensrf.dbmath>
+
+      <opensrf.settings>
+        <keepalive>1</keepalive>
+        <stateless>0</stateless>
+        <language>perl</language>
+        <implementation>OpenSRF::Application::Settings</implementation>
+        <max_requests>17</max_requests>
+        <unix_config>
+          <unix_sock>opensrf.settings_unix.sock</unix_sock>
+          <unix_pid>opoensrf.settings_unix.pid</unix_pid>
+          <max_requests>1000</max_requests>
+          <unix_log>opensrf.settings_unix.log</unix_log>
+          <min_children>5</min_children>
+          <max_children>15</max_children>
+          <min_spare_children>3</min_spare_children>
+          <max_spare_children>5</max_spare_children>
+        </unix_config>
+      </opensrf.settings>
+    </apps>
+  </default>
+
+  <hosts>
+
+    <myhost.mydomain.org>
+<!-- ^-=-
+       Must match the fully qualified domain name of the host 
+       on Linux, this is usually the output of "hostname -f"
+-->
+
+<!-- List all of the apps this server will be running -->
+      <activeapps>
+        <appname>opensrf.persist</appname>
+        <appname>opensrf.settings</appname>
+        <appname>opensrf.math</appname>
+        <appname>opensrf.dbmath</appname>
+      </activeapps>
+
+      <apps>
+
+<!-- Example of an app-specific setting override -->
+        <opensrf.persist>
+          <app_settings>
+            <dbfile>/different/path/to/dbfile/persist.db</dbfile>
+          </app_settings>
+        </opensrf.persist>
+
+      </apps>
+
+    </myhost.mydomain.org>
+
+  </hosts>
 
 </opensrf>
index 708d4a6..d24121d 100644 (file)
-<?xml version='1.0'?>
-
+<?xml version="1.0"?>
 <config>
 
-  <opensrf> <!-- bootstrap config for OpenSRF apps -->
-
-               <!--  the routers's name on the network -->
-               <!-- do not change this -->
-      <router_name>router</router_name>
-               
-      <routers> 
-                       <!-- 
-                               list of router domains we should register with. 
-                               We must at least have our default jabber domain in here
-                       -->
-         <router>localhost</router>
-      </routers>
-
-      <domains>
-      <!-- Our jabber domain, currently only one domain is supported -->
-         <domain>localhost</domain>
-      </domains>
+  <!-- bootstrap config for OpenSRF apps -->
+  <opensrf>
 
-      <username>client</username>
-      <passwd>mypass</passwd>
-      <port>5222</port>
+    <!-- The OpenSRF Routers's name on the network -->
+    <!-- You should never need to change thischange this -->
+    <router_name>router</router_name>
+
+    <routers>
 
-               <!-- log to a local file -->
-      <logfile>/openils/var/log/osrfsys.log</logfile>
+      <!-- List of router domains we should register with. 
+        We must at least have our default jabber domain in here -->
+      <router>localhost</router>
+
+    </routers>
+    <domains>
+
+      <!-- Our jabber domain, currently only one domain is supported -->
+      <domain>localhost</domain>
 
-               <!-- 
-                       Log to syslog. You can use this same layout for 
-                       defining the logging of all services in this file 
-               -->
+    </domains>
+    <username>client</username>
+    <passwd>mypass</passwd>
+    <port>5222</port>
 
-               <!--
-               <logfile>syslog</logfile>
-               <syslog>local2</syslog>
-               <actlog>local1</actlog>
-               -->
+    <!-- log to a local file -->
+    <logfile>/openils/var/log/osrfsys.log</logfile>
 
-               <!-- 0 None, 1 Error, 2 Warning, 3 Info, 4 debug, 5 Internal (Nasty) -->
-      <loglevel>3</loglevel>
+    <!-- Log to syslog. You can use this same layout for 
+        defining the logging of all services in this file -->
+<!--
+    <logfile>syslog</logfile>
+    <syslog>local2</syslog>
+    <actlog>local1</actlog>
+-->
+
+    <!-- 0 None, 1 Error, 2 Warning, 3 Info, 4 debug, 5 Internal (Nasty) -->
+    <loglevel>3</loglevel>
 
     <!-- config file for the services -->
     <settings_config>/openils/conf/opensrf.xml</settings_config>
+
   </opensrf>
 
-       <!-- Update this if you use ChopChop -->
-       <chopchop> <!-- Our jabber server -->
-               <domain>localhost</domain>
-               <port>5222</port>
+  <!-- Update this if you use ChopChop -->
+  <chopchop>
 
-               <!-- used when multiple servers need to communicate -->
-               <s2sport>5269</s2sport>
-               <secret>secret</secret>
+    <!-- Our jabber server -->
+    <domain>localhost</domain>
+    <port>5222</port>
 
-               <listen_address>10.0.0.3</listen_address>
-               <loglevel>3</loglevel>
-               <logfile>/openils/var/log/osrfsys.log</logfile>
-       </chopchop>
+    <!-- used when multiple servers need to communicate -->
+    <s2sport>5269</s2sport>
+    <secret>secret</secret>
+    <listen_address>10.0.0.3</listen_address>
+    <loglevel>3</loglevel>
+    <logfile>/openils/var/log/osrfsys.log</logfile>
+  </chopchop>
 
-       <!-- The section between <gateway>...</gateway> is a standard OpenSRF C stack config file -->
-       <gateway>
+  <!-- The section between <gateway>...</gateway> is a standard OpenSRF C stack config file -->
+  <gateway>
 
-        <!-- we consider ourselves to be the "originating" client for requests,
+    <!-- we consider ourselves to be the "originating" client for requests,
             which means we define the log XID string for log traces -->
-        <client>true</client>
-
-               <!--  the routers's name on the network -->
-               <router_name>router</router_name>
-
-               <!-- jabber domains to connect to (domain1, domain2, ...) -->
-               <domains>
-                       <domain>localhost</domain>
-               </domains>
-
-               <!-- These are the services that the gateway will serve. 
-                       Any other requests will receive an HTTP_NOT_FOUND (404) 
-                       DO NOT put any services here that you don't want the internet to have access to
-                       -->
-               <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 -->
-               <username>mylogin</username>
-               <passwd>mypassword</passwd>
-               <port>5222</port>
-       
-               <logfile>/openils/var/log/gateway.log</logfile>
-               <loglevel>3</loglevel>
-
-       </gateway>
-
-
-       <!-- ======================================================================================== -->
-
-       <router>
-
-               <!-- do not change -->
-               <component>0</component>
-       
-               <trusted_domains>
-                       <!-- Trusted servers are allowed to register apps with the router -->
-                       <server>localhost</server>
-                       <!-- Trusted clients are allowed to send packets through the router -->
-                       <client>localhost</client>
-               </trusted_domains>
-       
-               <transport>
-                       <!-- jabber server are we connecting to -->
-                       <server>localhost</server>
-                       <port>5222</port>
-
-                       <!-- if this is changed, all "router_name" settings 
+    <client>true</client>
+
+    <!--  the routers's name on the network -->
+    <router_name>router</router_name>
+
+    <!-- jabber domains to connect to (domain1, domain2, ...) -->
+    <domains>
+      <domain>localhost</domain>
+    </domains>
+
+<!-- These are the services that the gateway will serve. 
+       Any other requests will receive an HTTP_NOT_FOUND (404) 
+       DO NOT put any services here that you don't want the internet to have access to
+-->
+    <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 -->
+    <username>mylogin</username>
+    <passwd>mypassword</passwd>
+    <port>5222</port>
+    <logfile>/openils/var/log/gateway.log</logfile>
+    <loglevel>3</loglevel>
+
+  </gateway>
+
+  <!-- ======================================================================================== -->
+
+  <router>
+
+    <!-- do not change -->
+    <component>0</component>
+
+    <trusted_domains>
+
+      <!-- Trusted servers are allowed to register apps with the router -->
+      <server>localhost</server>
+
+      <!-- Trusted clients are allowed to send packets through the router -->
+      <client>localhost</client>
+
+    </trusted_domains>
+
+    <transport>
+
+      <!-- jabber server are we connecting to -->
+      <server>localhost</server>
+      <port>5222</port>
+
+      <!-- if this is changed, all "router_name" settings 
                 will need to be updated to match this setting -->
-                       <username>router</username>
+      <username>router</username>
+      <password>mypassword</password>
 
-                       <password>mypassword</password>
+      <!-- router's jabber resource -->
+      <!-- do not change this -->
+      <resource>router</resource>
+      <connect_timeout>10</connect_timeout>
+      <max_reconnect_attempts>5</max_reconnect_attempts>
 
-                       <!-- router's jabber resource --> 
-                       <!-- do not change this -->
-                       <resource>router</resource>
+    </transport>
+    <logfile>/openils/var/log/router.log</logfile>
+    <loglevel>3</loglevel>
 
-                       <connect_timeout>10</connect_timeout>
-                       <max_reconnect_attempts>5</max_reconnect_attempts>
-               </transport>
-       
-               <logfile>/openils/var/log/router.log</logfile>
-               <loglevel>3</loglevel>
-       
-       </router>
+  </router>
 
-       <!-- ======================================================================================== -->
+  <!-- ======================================================================================== -->
 
 </config>
index 5bc1e2d..e88ae6b 100644 (file)
@@ -1,12 +1,13 @@
-<!-- This file follows the standard C stack bootstrap config file layout -->
+<?xml version="1.0"?>
+<!-- This file follows the standard bootstrap config file layout found in opensrf_core.xml -->
 <srfsh>
-       <router_name>router</router_name>
-       <domains>
-               <domain>127.0.0.1</domain> 
-       </domains>
-       <username>myusername</username>
-       <passwd>mypassword</passwd>
-       <port>5222</port>
-       <logfile>/path/to/log/srfsh.log</logfile>
-       <loglevel>4</loglevel>
+  <router_name>router</router_name>
+  <domains>
+    <domain>127.0.0.1</domain>
+  </domains>
+  <username>myusername</username>
+  <passwd>mypassword</passwd>
+  <port>5222</port>
+  <logfile>/path/to/log/srfsh.log</logfile>
+  <loglevel>4</loglevel>
 </srfsh>
index ede5d91..a1f785b 100644 (file)
@@ -23,6 +23,7 @@ GNU General Public License for more details.
 #define JSON_PARSER_H
 
 #include <stdio.h>
+#include <ctype.h>
 #include <objson/object.h>
 #include <opensrf/utils.h>
 
@@ -77,9 +78,6 @@ int json_eat_comment(char* string, unsigned long* index, char** class_hint, int
 /* prints a useful error message to stderr. always returns -1 */
 int json_handle_error(char* string, unsigned long* index, char* err_msg);
 
-/* returns true if c is 0-9 */
-int is_number(char c);
-
 int json_parse_json_null(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
 
 
index f290cdc..555a211 100644 (file)
@@ -67,19 +67,19 @@ void socket_manager_free(socket_manager* mgr);
 /* creates a new server socket node and adds it to the socket set.
        returns socket id on success.  -1 on failure.
        socket_type is one of INET or UNIX  */
-int socket_open_tcp_server(socket_manager*, int port, char* listen_ip );
+int socket_open_tcp_server(socket_manager*, int port, const char* listen_ip );
 
 int socket_open_unix_server(socket_manager* mgr, char* path);
 
-int socket_open_udp_server( socket_manager* mgr, int port, char* listen_ip );
+int socket_open_udp_server( socket_manager* mgr, int port, const char* listen_ip );
 
 /* creates a client TCP socket and adds it to the socket set.
        returns 0 on success.  -1 on failure.  */
-int socket_open_tcp_client(socket_manager*, int port, char* dest_addr);
+int socket_open_tcp_client(socket_manager*, int port, const char* dest_addr);
 
 /* creates a client UNIX socket and adds it to the socket set.
        returns 0 on success.  -1 on failure.  */
-int socket_open_unix_client(socket_manager*, char* sock_path);
+int socket_open_unix_client(socket_manager*, const char* sock_path);
 
 int socket_open_udp_client( socket_manager* mgr, int port, char* dest_addr);
 
index 0cf5657..14823ab 100644 (file)
@@ -86,7 +86,6 @@ opensrf-install:      objson-install
        cp -r ../include/opensrf $(INCLUDEDIR)
        cp libopensrf/opensrf $(BINDIR)/opensrf-c
        make -C c-apps install
-       cp ../examples/bootstrap.conf.example $(ETCDIR)
        cp ../bin/osrf_ctl.sh $(BINDIR)
        cp ../examples/opensrf.xml.example $(ETCDIR)
        cp ../examples/opensrf_core.xml.example $(ETCDIR)
index 2585719..9a20bd6 100644 (file)
@@ -19,7 +19,10 @@ GNU General Public License for more details.
 #include <time.h>
 
 static int osrfChatXMLErrorOcurred = 0;
-static int osrfChatClientSentDisconnect = 0;
+
+/* This is used by code in osrfChatPushData, but that code is
+   currently commented out.  Uncomment the next line if needed. */
+//static int osrfChatClientSentDisconnect = 0;
 
 /* shorter version of strcmp */
 static int eq(const char* a, const char* b) { return (a && b && !strcmp(a,b)); }
@@ -613,7 +616,7 @@ int osrfChatHandleConnected( osrfChatNode* node, const char* name, const xmlChar
        if(eq(name,"message")) {
 
                /* drop the old message and start with a new one */
-               xmlNodePtr root = xmlNewNode(NULL, name);
+               xmlNodePtr root = xmlNewNode(NULL, BAD_CAST name);
                xmlAddAttrs(root, atts);
                xmlNodePtr oldRoot = xmlDocSetRootElement(node->msgDoc, root);
                free(node->to);
@@ -628,7 +631,7 @@ int osrfChatHandleConnected( osrfChatNode* node, const char* name, const xmlChar
        } else {
 
                /* all non "message" nodes are simply added to the message */
-               xmlNodePtr nodep = xmlNewNode(NULL, name);
+               xmlNodePtr nodep = xmlNewNode(NULL, BAD_CAST name);
                xmlAddAttrs(nodep, atts);
                xmlAddChild(xmlDocGetRootElement(node->msgDoc), nodep);
        }
index 5532f73..3b6f6fd 100644 (file)
@@ -9,9 +9,6 @@ int main( int argc, char* argv[] ) {
                return 1;
        }
 
-       fprintf(stderr, "Loading OpenSRF host %s with bootstrap config %s "
-                       "and config context %s\n", argv[1], argv[2], argv[3] );
-
        /* these must be strdup'ed because init_proc_title / set_proc_title 
                are evil and overwrite the argv memory */
        char* host              = strdup( argv[1] );
index 01a97cc..36b203c 100644 (file)
@@ -69,14 +69,14 @@ int osrf_prefork_run(char* appname) {
        prefork_simple* forker = prefork_simple_init(
                osrfSystemGetTransportClient(), maxr, minc, maxc);
 
-       forker->appname = strdup(appname);
-       forker->keepalive       = kalive;
-
        if(forker == NULL) {
                osrfLogError( OSRF_LOG_MARK, "osrf_prefork_run() failed to create prefork_simple object");
                return -1;
        }
 
+       forker->appname = strdup(appname);
+       forker->keepalive       = kalive;
+
        prefork_launch_children(forker);
 
        osrf_prefork_register_routers(appname);
index c378b7b..e5596dd 100644 (file)
@@ -79,7 +79,12 @@ int osrfSystemBootstrap( char* hostname, char* configfile, char* contextNode ) {
                        hostname, configfile );
                return -1;
        }
-       
+
+       /** daemonize me **/
+       /* background and let our children do their thing */
+       /* NOTE: This has been moved from below the 'if (apps)' block below ... move it back if things go crazy */
+       daemonize();
+
        jsonObject* apps = osrf_settings_host_value_object("/activeapps/appname");
        osrfStringArray* arr = osrfNewStringArray(8);
        
@@ -122,7 +127,7 @@ int osrfSystemBootstrap( char* hostname, char* configfile, char* contextNode ) {
        
                                } else {
                
-                                       fprintf(stderr, " * Running application %s\n", appname);
+                                       osrfLogError( OSRF_LOG_MARK, " * Running application %s\n", appname);
                                        if( osrfAppRegisterApplication( appname, libfile ) == 0 ) 
                                                osrf_prefork_run(appname);
        
@@ -131,27 +136,22 @@ int osrfSystemBootstrap( char* hostname, char* configfile, char* contextNode ) {
                                }
                        } // language == c
                } 
+       } // should we do something if there are no apps? does the wait(NULL) below do that for us?
+
+       while(1) {
+               errno = 0;
+               pid_t pid = wait(NULL);
+               if(-1 == pid) {
+                       if(errno == ECHILD)
+                               osrfLogError(OSRF_LOG_MARK, "We have no more live services... exiting");
+                       else
+                               osrfLogError(OSRF_LOG_MARK, "Exiting top-level system loop with error: %s", strerror(errno));
+                       break;
+               } else {
+                       osrfLogError(OSRF_LOG_MARK, "We lost a top-level service process with PID %ld", pid);
+               }
        }
 
-       /** daemonize me **/
-
-       /* background and let our children do their thing */
-       daemonize();
-    while(1) {
-        errno = 0;
-        pid_t pid = wait(NULL);
-        if(-1 == pid) {
-            if(errno == ECHILD)
-                osrfLogError(OSRF_LOG_MARK, "We have no more live services... exiting");
-            else
-                osrfLogError(OSRF_LOG_MARK, "Exiting top-level system loop with error: %s", strerror(errno));
-            break;
-        } else {
-            osrfLogError(OSRF_LOG_MARK, "We lost a top-level service process with PID %ld", pid);
-        }
-    }
-
-
        return 0;
 }
 
index 6196410..6dc91b0 100644 (file)
@@ -77,7 +77,7 @@ static socket_node* _socket_add_node(socket_manager* mgr,
 /* creates a new server socket node and adds it to the socket set.
        returns new socket fd on success.  -1 on failure.
        socket_type is one of INET or UNIX  */
-int socket_open_tcp_server(socket_manager* mgr, int port, char* listen_ip) {
+int socket_open_tcp_server(socket_manager* mgr, int port, const char* listen_ip) {
 
        if( mgr == NULL ) {
                osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_server(): NULL mgr"); 
@@ -98,7 +98,13 @@ int socket_open_tcp_server(socket_manager* mgr, int port, char* listen_ip) {
        server_addr.sin_family = AF_INET;
 
        if(listen_ip != NULL) {
-               server_addr.sin_addr.s_addr = inet_addr(listen_ip);
+               struct in_addr addr;
+               if( inet_aton( listen_ip, &addr ) )
+                       server_addr.sin_addr.s_addr = addr.s_addr;
+               else {
+                       osrfLogError( OSRF_LOG_MARK, "Listener address is invalid: %s", listen_ip );
+                       return -1;
+               }
        } else {
                server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        }
@@ -175,7 +181,7 @@ int socket_open_unix_server(socket_manager* mgr, char* path) {
 
 
 int socket_open_udp_server( 
-               socket_manager* mgr, int port, char* listen_ip ) {
+               socket_manager* mgr, int port, const char* listen_ip ) {
 
        int sockfd;
        struct sockaddr_in server_addr;
@@ -188,8 +194,15 @@ int socket_open_udp_server(
 
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(port);
-       if(listen_ip) server_addr.sin_addr.s_addr = inet_addr(listen_ip);
-       else server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+       if(listen_ip) {
+               struct in_addr addr;
+               if( inet_aton( listen_ip, &addr ) )
+                       server_addr.sin_addr.s_addr = addr.s_addr;
+               else {
+                       osrfLogError( OSRF_LOG_MARK, "UDP listener address is invalid: %s", listen_ip );
+                       return -1;
+               }
+       } else server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 
        errno = 0;
        if( (bind (sockfd, (struct sockaddr *) &server_addr,sizeof(server_addr))) ) {
@@ -203,7 +216,7 @@ int socket_open_udp_server(
 }
 
 
-int socket_open_tcp_client(socket_manager* mgr, int port, char* dest_addr) {
+int socket_open_tcp_client(socket_manager* mgr, int port, const char* dest_addr) {
 
        struct sockaddr_in remoteAddr, localAddr;
    struct hostent *hptr;
@@ -318,7 +331,7 @@ int socket_open_udp_client(
 }
 
 
-int socket_open_unix_client(socket_manager* mgr, char* sock_path) {
+int socket_open_unix_client(socket_manager* mgr, const char* sock_path) {
 
        int sock_fd, len;
    struct sockaddr_un usock;
index 5c6862b..6488115 100644 (file)
@@ -95,7 +95,7 @@ transport_message* new_message_from_xml( const char* msg_xml ) {
                xmlFree(router_class);
        }
        if(broadcast) {
-               if(strcmp(broadcast,"0") )
+               if(strcmp((char*) broadcast,"0") )
                        new_msg->broadcast      = 1;
                xmlFree(broadcast);
        }
@@ -211,9 +211,9 @@ int message_free( transport_message* msg ){
 // ---------------------------------------------------------------------------------
 char* message_to_xml( const transport_message* msg ) {
 
-       int                     bufsize;
+       //int                   bufsize;
        //xmlChar*              xmlbuf;
-       char*                   encoded_body;
+       //char*                 encoded_body;
 
        xmlNodePtr      message_node;
        xmlNodePtr      body_node;
index 43483f0..4fb0290 100644 (file)
@@ -332,7 +332,7 @@ void startElementHandler(
        if( ! ses ) { return; }
 
        
-       if( strcmp( name, "message" ) == 0 ) {
+       if( strcmp( (char*) name, "message" ) == 0 ) {
                ses->state_machine->in_message = 1;
                buffer_add( ses->from_buffer, get_xml_attr( atts, "from" ) );
                buffer_add( ses->recipient_buffer, get_xml_attr( atts, "to" ) );
@@ -350,37 +350,37 @@ void startElementHandler(
 
        if( ses->state_machine->in_message ) {
 
-               if( strcmp( name, "body" ) == 0 ) {
+               if( strcmp( (char*) name, "body" ) == 0 ) {
                        ses->state_machine->in_message_body = 1;
                        return;
                }
        
-               if( strcmp( name, "subject" ) == 0 ) {
+               if( strcmp( (char*) name, "subject" ) == 0 ) {
                        ses->state_machine->in_subject = 1;
                        return;
                }
        
-               if( strcmp( name, "thread" ) == 0 ) {
+               if( strcmp( (char*) name, "thread" ) == 0 ) {
                        ses->state_machine->in_thread = 1;
                        return;
                }
 
        }
 
-       if( strcmp( name, "presence" ) == 0 ) {
+       if( strcmp( (char*) name, "presence" ) == 0 ) {
                ses->state_machine->in_presence = 1;
                buffer_add( ses->from_buffer, get_xml_attr( atts, "from" ) );
                buffer_add( ses->recipient_buffer, get_xml_attr( atts, "to" ) );
                return;
        }
 
-       if( strcmp( name, "status" ) == 0 ) {
+       if( strcmp( (char*) name, "status" ) == 0 ) {
                ses->state_machine->in_status = 1;
                return;
        }
 
 
-       if( strcmp( name, "stream:error" ) == 0 ) {
+       if( strcmp( (char*) name, "stream:error" ) == 0 ) {
                ses->state_machine->in_error = 1;
                ses->state_machine->connected = 0;
                osrfLogWarning(  OSRF_LOG_MARK, "Received <stream:error> message from Jabber server" );
@@ -389,21 +389,21 @@ void startElementHandler(
 
 
        /* first server response from a connect attempt */
-       if( strcmp( name, "stream:stream" ) == 0 ) {
+       if( strcmp( (char*) name, "stream:stream" ) == 0 ) {
                if( ses->state_machine->connecting == CONNECTING_1 ) {
                        ses->state_machine->connecting = CONNECTING_2;
                        buffer_add( ses->session_id, get_xml_attr(atts, "id") );
                }
        }
 
-       if( strcmp( name, "handshake" ) == 0 ) {
+       if( strcmp( (char*) name, "handshake" ) == 0 ) {
                ses->state_machine->connected = 1;
                ses->state_machine->connecting = 0;
                return;
        }
 
 
-       if( strcmp( name, "error" ) == 0 ) {
+       if( strcmp( (char*) name, "error" ) == 0 ) {
                ses->state_machine->in_message_error = 1;
                buffer_add( ses->message_error_type, get_xml_attr( atts, "type" ) );
                ses->message_error_code = atoi( get_xml_attr( atts, "code" ) );
@@ -412,7 +412,7 @@ void startElementHandler(
                return;
        }
 
-       if( strcmp( name, "iq" ) == 0 ) {
+       if( strcmp( (char*) name, "iq" ) == 0 ) {
                ses->state_machine->in_iq = 1;
 
                if( strcmp( get_xml_attr(atts, "type"), "result") == 0 
@@ -433,7 +433,7 @@ char* get_xml_attr( const xmlChar** atts, char* attr_name ) {
        int i;
        if (atts != NULL) {
                for(i = 0;(atts[i] != NULL);i++) {
-                       if( strcmp( atts[i++], attr_name ) == 0 ) {
+                       if( strcmp( (char*) atts[i++], attr_name ) == 0 ) {
                                if( atts[i] != NULL ) {
                                        return (char*) atts[i];
                                }
@@ -451,7 +451,7 @@ void endElementHandler( void *session, const xmlChar *name) {
        transport_session* ses = (transport_session*) session;
        if( ! ses ) { return; }
 
-       if( strcmp( name, "message" ) == 0 ) {
+       if( strcmp( (char*) name, "message" ) == 0 ) {
 
 
                /* pass off the message info the callback */
@@ -489,22 +489,22 @@ void endElementHandler( void *session, const xmlChar *name) {
                return;
        }
        
-       if( strcmp( name, "body" ) == 0 ) {
+       if( strcmp( (char*) name, "body" ) == 0 ) {
                ses->state_machine->in_message_body = 0;
                return;
        }
 
-       if( strcmp( name, "subject" ) == 0 ) {
+       if( strcmp( (char*) name, "subject" ) == 0 ) {
                ses->state_machine->in_subject = 0;
                return;
        }
 
-       if( strcmp( name, "thread" ) == 0 ) {
+       if( strcmp( (char*) name, "thread" ) == 0 ) {
                ses->state_machine->in_thread = 0;
                return;
        }
        
-       if( strcmp( name, "iq" ) == 0 ) {
+       if( strcmp( (char*) name, "iq" ) == 0 ) {
                ses->state_machine->in_iq = 0;
                if( ses->message_error_code > 0 ) {
                        osrfLogWarning( OSRF_LOG_MARK,  "Error in IQ packet: code %d",  ses->message_error_code );
@@ -514,7 +514,7 @@ void endElementHandler( void *session, const xmlChar *name) {
                return;
        }
 
-       if( strcmp( name, "presence" ) == 0 ) {
+       if( strcmp( (char*) name, "presence" ) == 0 ) {
                ses->state_machine->in_presence = 0;
                /*
                if( ses->presence_callback ) {
@@ -525,17 +525,17 @@ void endElementHandler( void *session, const xmlChar *name) {
                return;
        }
 
-       if( strcmp( name, "status" ) == 0 ) {
+       if( strcmp( (char*) name, "status" ) == 0 ) {
                ses->state_machine->in_status = 0;
                return;
        }
 
-       if( strcmp( name, "error" ) == 0 ) {
+       if( strcmp( (char*) name, "error" ) == 0 ) {
                ses->state_machine->in_message_error = 0;
                return;
        }
 
-       if( strcmp( name, "error:error" ) == 0 ) {
+       if( strcmp( (char*) name, "error:error" ) == 0 ) {
                ses->state_machine->in_error = 0;
                return;
        }
index 07ed9a2..908145b 100644 (file)
@@ -13,12 +13,13 @@ GNU General Public License for more details.
 */
 
 #include <opensrf/utils.h>
+#include <opensrf/log.h>
 #include <errno.h>
 
 inline void* safe_malloc( int size ) {
        void* ptr = (void*) malloc( size );
        if( ptr == NULL ) {
-               perror("safe_malloc(): Out of Memory" );
+               osrfLogError( OSRF_LOG_MARK, "Out of Memory" );
                exit(99);
        }
        memset( ptr, 0, size );
@@ -189,7 +190,7 @@ int buffer_add(growing_buffer* gb, char* data) {
                }
        
                if( gb->size > BUFFER_MAX_SIZE ) {
-                       fprintf(stderr, "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
+                       osrfLogError( OSRF_LOG_MARK, "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
                        buffer_free( gb );
                        return 0;
                }
@@ -366,20 +367,34 @@ char* uescape( const char* string, int size, int full_escape ) {
 }
 
 
-// A function to turn a process into a daemon and set it's process name in ps/top
+// A function to turn a process into a daemon 
 int daemonize() {
-       int f = fork();
+       pid_t f = fork();
 
        if (f == -1) {
-               perror("Failed to fork!");
+               osrfLogError( OSRF_LOG_MARK, "Failed to fork!" );
                return -1;
 
        } else if (f == 0) { // We're in the child now...
+               
+               // Change directories.  Otherwise whatever directory
+               // we're in couldn't be deleted until the program
+               // terminated -- possibly causing some inconvenience.
+               chdir( "/" );
+
+               /* create new session */
                setsid();
+
+               // Now that we're no longer attached to a terminal,
+               // we don't want any traffic on the standard streams
+               freopen( "/dev/null", "r", stdin );
+               freopen( "/dev/null", "w", stdout );
+               freopen( "/dev/null", "w", stderr );
+               
                return 0;
 
        } else { // We're in the parent...
-               exit(0);
+               _exit(0);
        }
 }
 
@@ -406,10 +421,7 @@ char* file_to_string(const char* filename) {
 
        FILE* file = fopen(filename, "r");
        if(!file) {
-               int l = strlen(filename) + 64;
-               char b[l];
-               snprintf(b,l,"Unable to open file [%s] in file_to_string()", filename);
-               perror(b);
+               osrfLogError( OSRF_LOG_MARK, "Unable to open file [%s]", filename );
                return NULL;
        }
 
index e3ef206..ec9e5c3 100644 (file)
@@ -97,7 +97,7 @@ char* xmlSaxAttr( const xmlChar** atts, char* name ) {
        if( atts && name ) {
                int i;
                for(i = 0; (atts[i] != NULL); i++) {
-                       if(!strcmp(atts[i], name)) {
+                       if(!strcmp((char*) atts[i], name)) {
                                if(atts[++i]) return (char*) atts[i];
                        }
                }
index 8313872..18cd2a8 100644 (file)
@@ -127,7 +127,7 @@ int _json_parse_string(char* string, unsigned long* index, jsonObject* obj, int
                        break;
 
                default:
-                       if(is_number(c) || c == '.' || c == '-') { /* are we a number? */
+                       if(isdigit(c) || c == '.' || c == '-') { /* are we a number? */
                                status = json_parse_json_number(string, index, obj, current_strlen);    
                                if(status) return status;
                                break;
@@ -225,7 +225,7 @@ int json_parse_json_number(char* string, unsigned long* index, jsonObject* obj,
 
        while(*index < current_strlen) {
 
-               if(is_number(c)) {
+               if(isdigit(c)) {
                        buffer_add_char(buf, c);
                }
 
@@ -503,18 +503,18 @@ int json_parse_json_string(char* string, unsigned long* index, jsonObject* obj,
        
                                        if (ucs_char < 0x80) {
                                                utf_out[0] = ucs_char;
-                                               buffer_add(buf, utf_out);
+                                               buffer_add(buf, (char*) utf_out);
 
                                        } else if (ucs_char < 0x800) {
                                                utf_out[0] = 0xc0 | (ucs_char >> 6);
                                                utf_out[1] = 0x80 | (ucs_char & 0x3f);
-                                               buffer_add(buf, utf_out);
+                                               buffer_add(buf, (char*) utf_out);
 
                                        } else {
                                                utf_out[0] = 0xe0 | (ucs_char >> 12);
                                                utf_out[1] = 0x80 | ((ucs_char >> 6) & 0x3f);
                                                utf_out[2] = 0x80 | (ucs_char & 0x3f);
-                                               buffer_add(buf, utf_out);
+                                               buffer_add(buf, (char*) utf_out);
                                        }
                                        /* ----------------------------------------------------------------------- */
                                        /* ----------------------------------------------------------------------- */
@@ -692,23 +692,6 @@ int json_eat_comment(char* string, unsigned long* index, char** buffer, int pars
        return 0;
 }
 
-int is_number(char c) {
-       switch(c) {
-               case '0':
-               case '1':
-               case '2':
-               case '3':
-               case '4':
-               case '5':
-               case '6':
-               case '7':
-               case '8':
-               case '9':
-                       return 1;
-       }
-       return 0;
-}
-
 int json_handle_error(char* string, unsigned long* index, char* err_msg) {
 
        char buf[60];
diff --git a/src/perlmods/JSON.pm b/src/perlmods/JSON.pm
deleted file mode 100644 (file)
index 2128f96..0000000
+++ /dev/null
@@ -1,827 +0,0 @@
-
-package JSON::number;
-sub new {
-       my $class = shift;
-       my $x = shift || $class;
-       return bless \$x => __PACKAGE__;
-}
-
-use overload ( '""' => \&toString );
-
-sub toString { defined($_[1]) ? ${$_[1]} : ${$_[0]} }
-
-package JSON::bool::true;
-sub new { return bless {} => __PACKAGE__ }
-use overload ( '""' => \&toString );
-use overload ( 'bool' => sub { 1 } );
-use overload ( '0+' => sub { 1 } );
-
-sub toString { 'true' }
-
-package JSON::bool::false;
-sub new { return bless {} => __PACKAGE__ }
-use overload ( '""' => \&toString );
-use overload ( 'bool' => sub { 0 } );
-use overload ( '0+' => sub { 0 } );
-
-sub toString { 'false' }
-
-package JSON;
-use Unicode::Normalize;
-use vars qw/%_class_map/;
-
-sub register_class_hint {
-       my $class = shift;
-       my %args = @_;
-
-       $_class_map{hints}{$args{hint}} = \%args;
-       $_class_map{classes}{$args{name}} = \%args;
-}
-
-sub _JSON_regex {
-       my $string = shift;
-
-       $string =~ s/^\s* ( 
-                          {                            | # start object
-                          \[                           | # start array
-                          -?\d+\.?\d*                  | # number literal
-                          "(?:(?:\\[\"])|[^\"])*"      | # string literal
-                          (?:\/\*.+?\*\/)              | # C comment
-                          true                         | # bool true
-                          false                        | # bool false
-                          null                         | # undef()
-                          :                            | # object key-value sep
-                          ,                            | # list sep
-                          \]                           | # array end
-                          }                              # object end
-                       )
-                \s*//sox;
-       return ($string,$1);
-}
-
-sub lookup_class {
-       my $self = shift;
-       my $hint = shift;
-       return $_class_map{hints}{$hint}{name}
-}
-
-sub lookup_hint {
-       my $self = shift;
-       my $class = shift;
-       return $_class_map{classes}{$class}{hint}
-}
-
-sub _json_hint_to_class {
-       my $type = shift;
-       my $hint = shift;
-
-       return $_class_map{hints}{$hint}{name} if (exists $_class_map{hints}{$hint});
-       
-       $type = 'hash' if ($type eq '}');
-       $type = 'array' if ($type eq ']');
-
-       JSON->register_class_hint(name => $hint, hint => $hint, type => $type);
-
-       return $hint;
-}
-
-sub JSON2perl {
-       my $class = shift;
-       local $_ = shift;
-
-       s/(?<!\\)\$/\\\$/gmo; # fixup $ for later
-       s/(?<!\\)\@/\\\@/gmo; # fixup @ for later
-       s/(?<!\\)\%/\\\%/gmo; # fixup % for later
-
-       # Convert JSON Unicode...
-       s/\\u([0-9a-fA-F]{4})/chr(hex($1))/esog;
-
-       # handle class blessings
-       s/\/\*--\s*S\w*?\s+\S+\s*--\*\// bless(/sog;
-       s/(\]|\}|")\s*\/\*--\s*E\w*?\s+(\S+)\s*--\*\//$1 => _json_hint_to_class("$1", "$2")) /sog;
-
-       my $re = qr/((?<!\\)"(?>(?<=\\)"|[^"])*(?<!\\)")/;
-       # Grab strings...
-       my @strings = /$re/sog;
-
-       # Replace with code...
-       #s/"(?:(?:\\[\"])|[^\"])*"/ do{ \$t = '"'.shift(\@strings).'"'; eval \$t;} /sog;
-       s/$re/ eval shift(\@strings) /sog;
-
-       # Perlify hash notation
-       s/:/ => /sog;
-
-       # Do numbers...
-       #s/\b(-?\d+\.?\d*)\b/ JSON::number::new($1) /sog;
-
-       # Change javascript stuff to perl...
-       s/null/ undef /sog;
-       s/true/ bless( {}, "JSON::bool::true") /sog;
-       s/false/ bless( {}, "JSON::bool::false") /sog;
-
-       my $ret;
-       return eval '$ret = '.$_;
-}
-
-my $_json_index;
-sub ___JSON2perl {
-       my $class = shift;
-       my $data = shift;
-
-       $data = [ split //, $data ];
-
-       $_json_index = 0;
-
-       return _json_parse_data($data);
-}
-
-sub _eat_WS {
-       my $data = shift;
-       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-}
-
-sub _json_parse_data {
-       my $data = shift;
-
-       my $out; 
-
-       #warn "parse_data";
-
-       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-
-       my $class = '';
-
-       my $c = $$data[$_json_index];
-
-       if ($c eq '/') {
-               $_json_index++;
-               $class = _json_parse_comment($data);
-               
-               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-               $c = $$data[$_json_index];
-       }
-
-       if ($c eq '"') {
-               $_json_index++;
-               my $val = '';
-
-               my $seen_slash = 0;
-               my $done = 0;
-               while (!$done) {
-                       my $c = $$data[$_json_index];
-                       #warn "c is $c";
-
-                       if ($c eq '\\') {
-                               if ($seen_slash) {
-                                       $val .= '\\';
-                                       $seen_slash = 0;
-                               } else {
-                                       $seen_slash = 1;
-                               }
-                       } elsif ($c eq '"') {
-                               if ($seen_slash) {
-                                       $val .= '"';
-                                       $seen_slash = 0;
-                               } else {
-                                       $done = 1;
-                               }
-                       } elsif ($c eq 't') {
-                               if ($seen_slash) {
-                                       $val .= "\t";
-                                       $seen_slash = 0;
-                               } else {
-                                       $val .= 't';
-                               }
-                       } elsif ($c eq 'b') {
-                               if ($seen_slash) {
-                                       $val .= "\b";
-                                       $seen_slash = 0;
-                               } else {
-                                       $val .= 'b';
-                               }
-                       } elsif ($c eq 'f') {
-                               if ($seen_slash) {
-                                       $val .= "\f";
-                                       $seen_slash = 0;
-                               } else {
-                                       $val .= 'f';
-                               }
-                       } elsif ($c eq 'r') {
-                               if ($seen_slash) {
-                                       $val .= "\r";
-                                       $seen_slash = 0;
-                               } else {
-                                       $val .= 'r';
-                               }
-                       } elsif ($c eq 'n') {
-                               if ($seen_slash) {
-                                       $val .= "\n";
-                                       $seen_slash = 0;
-                               } else {
-                                       $val .= 'n';
-                               }
-                       } elsif ($c eq 'u') {
-                               if ($seen_slash) {
-                                       $_json_index++;
-                                       $val .= chr(hex(join('',$$data[$_json_index .. $_json_index + 3])));
-                                       $_json_index += 3;
-                                       $seen_slash = 0;
-                               } else {
-                                       $val .= 'u';
-                               }
-                       } else {
-                               $val .= $c;
-                       }
-                       $_json_index++;
-
-                       #warn "string is $val";
-               }
-
-               $out = $val;
-
-               #$out = _json_parse_string($data);
-       } elsif ($c eq '[') {
-               $_json_index++;
-               $out = [];
-
-               my $in_parse = 0;
-               my $done = 0;
-               while(!$done) {
-                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-
-                       if ($$data[$_json_index] eq ']') {
-                               $done = 1;
-                               $_json_index++;
-                               last;
-                       }
-
-                       if ($in_parse) {
-                               if ($$data[$_json_index] ne ',') {
-                                       #warn "_json_parse_array: bad data, leaving array parser";
-                                       last;
-                               }
-                               $_json_index++;
-                               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-                       }
-
-                       my $item = _json_parse_data($data);
-
-                       push @$out, $item;
-                       $in_parse++;
-               }
-
-               #$out = _json_parse_array($data);
-       } elsif ($c eq '{') {
-               $_json_index++;
-               $out = {};
-
-               my $in_parse = 0;
-               my $done = 0;
-               while(!$done) {
-                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-
-                       if ($$data[$_json_index] eq '}') {
-                               $done = 1;
-                               $_json_index++;
-                               last;
-                       }
-
-                       if ($in_parse) {
-                               if ($$data[$_json_index] ne ',') {
-                                       #warn "_json_parse_object: bad data, leaving object parser";
-                                       last;
-                               }
-                               $_json_index++;
-                               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-                       }
-
-                       my ($key,$value);
-                       $key = _json_parse_data($data);
-
-                       #warn "object key is $key";
-
-                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-               
-                       if ($$data[$_json_index] ne ':') {
-                               #warn "_json_parse_object: bad data, leaving object parser";
-                               last;
-                       }
-                       $_json_index++;
-                       $value = _json_parse_data($data);
-
-                       $out->{$key} = $value;
-                       $in_parse++;
-               }
-               #$out = _json_parse_object($data);
-       } elsif (lc($c) eq 'n') {
-               if (lc(join('',$$data[$_json_index .. $_json_index + 3])) eq 'null') {
-                       $_json_index += 4;
-               } else {
-                       warn "CRAP! bad null parsing...";
-               }
-               $out = undef;
-               #$out = _json_parse_null($data);
-       } elsif (lc($c) eq 't' or lc($c) eq 'f') {
-               if (lc(join('',$$data[$_json_index .. $_json_index + 3])) eq 'true') {
-                       $out = 1;
-                       $_json_index += 4;
-               } elsif (lc(join('',$$data[$_json_index .. $_json_index + 4])) eq 'false') {
-                       $out = 0;
-                       $_json_index += 5;
-               } else {
-                       #warn "CRAP! bad bool parsing...";
-                       $out = undef;
-               }
-               #$out = _json_parse_bool($data);
-       } elsif ($c =~ /\d+/o or $c eq '.' or $c eq '-') {
-               my $val;
-               while ($$data[$_json_index] =~ /[-\.0-9]+/io) {
-                       $val .= $$data[$_json_index];
-                       $_json_index++;
-               }
-               $out = 0+$val;
-               #$out = _json_parse_number($data);
-       }
-
-       if ($class) {
-               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-               my $c = $$data[$_json_index];
-
-               if ($c eq '/') {
-                       $_json_index++;
-                       _json_parse_comment($data)
-               }
-
-               bless( $out => lookup_class($class) );
-       }
-
-       $out;
-}
-
-sub _json_parse_null {
-       my $data = shift;
-
-       #warn "parse_null";
-
-       if (lc(join('',$$data[$_json_index .. $_json_index + 3])) eq 'null') {
-               $_json_index += 4;
-       } else {
-               #warn "CRAP! bad null parsing...";
-       }
-       return undef;
-}
-
-sub _json_parse_bool {
-       my $data = shift;
-
-       my $out;
-
-       #warn "parse_bool";
-
-       if (lc(join('',$$data[$_json_index .. $_json_index + 3])) eq 'true') {
-               $out = 1;
-               $_json_index += 4;
-       } elsif (lc(join('',$$data[$_json_index .. $_json_index + 4])) eq 'false') {
-               $out = 0;
-               $_json_index += 5;
-       } else {
-               #warn "CRAP! bad bool parsing...";
-               $out = undef;
-       }
-       return $out;
-}
-
-sub _json_parse_number {
-       my $data = shift;
-
-       #warn "parse_number";
-
-       my $val;
-       while ($$data[$_json_index] =~ /[-\.0-9]+/io) {
-               $val .= $$data[$_json_index];
-               $_json_index++;
-       }
-
-       return 0+$val;
-}
-
-sub _json_parse_object {
-       my $data = shift;
-
-       #warn "parse_object";
-
-       my $out = {};
-
-       my $in_parse = 0;
-       my $done = 0;
-       while(!$done) {
-               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-
-               if ($$data[$_json_index] eq '}') {
-                       $done = 1;
-                       $_json_index++;
-                       last;
-               }
-
-               if ($in_parse) {
-                       if ($$data[$_json_index] ne ',') {
-                               #warn "_json_parse_object: bad data, leaving object parser";
-                               last;
-                       }
-                       $_json_index++;
-                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-               }
-
-               my ($key,$value);
-               $key = _json_parse_data($data);
-
-               #warn "object key is $key";
-
-               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-               
-               if ($$data[$_json_index] ne ':') {
-                       #warn "_json_parse_object: bad data, leaving object parser";
-                       last;
-               }
-               $_json_index++;
-               $value = _json_parse_data($data);
-
-               $out->{$key} = $value;
-               $in_parse++;
-       }
-
-       return $out;
-}
-
-sub _json_parse_array {
-       my $data = shift;
-
-       #warn "parse_array";
-
-       my $out = [];
-
-       my $in_parse = 0;
-       my $done = 0;
-       while(!$done) {
-               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-
-               if ($$data[$_json_index] eq ']') {
-                       $done = 1;
-                       $_json_index++;
-                       last;
-               }
-
-               if ($in_parse) {
-                       if ($$data[$_json_index] ne ',') {
-                               #warn "_json_parse_array: bad data, leaving array parser";
-                               last;
-                       }
-                       $_json_index++;
-                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-               }
-
-               my $item = _json_parse_data($data);
-
-               push @$out, $item;
-               $in_parse++;
-       }
-
-       return $out;
-}
-
-
-sub _json_parse_string {
-       my $data = shift;
-
-       #warn "parse_string";
-
-       my $val = '';
-
-       my $seen_slash = 0;
-       my $done = 0;
-       while (!$done) {
-               my $c = $$data[$_json_index];
-               #warn "c is $c";
-
-               if ($c eq '\\') {
-                       if ($seen_slash) {
-                               $val .= '\\';
-                               $seen_slash = 0;
-                       } else {
-                               $seen_slash = 1;
-                       }
-               } elsif ($c eq '"') {
-                       if ($seen_slash) {
-                               $val .= '"';
-                               $seen_slash = 0;
-                       } else {
-                               $done = 1;
-                       }
-               } elsif ($c eq 't') {
-                       if ($seen_slash) {
-                               $val .= "\t";
-                               $seen_slash = 0;
-                       } else {
-                               $val .= 't';
-                       }
-               } elsif ($c eq 'b') {
-                       if ($seen_slash) {
-                               $val .= "\b";
-                               $seen_slash = 0;
-                       } else {
-                               $val .= 'b';
-                       }
-               } elsif ($c eq 'f') {
-                       if ($seen_slash) {
-                               $val .= "\f";
-                               $seen_slash = 0;
-                       } else {
-                               $val .= 'f';
-                       }
-               } elsif ($c eq 'r') {
-                       if ($seen_slash) {
-                               $val .= "\r";
-                               $seen_slash = 0;
-                       } else {
-                               $val .= 'r';
-                       }
-               } elsif ($c eq 'n') {
-                       if ($seen_slash) {
-                               $val .= "\n";
-                               $seen_slash = 0;
-                       } else {
-                               $val .= 'n';
-                       }
-               } elsif ($c eq 'u') {
-                       if ($seen_slash) {
-                               $_json_index++;
-                               $val .= chr(hex(join('',$$data[$_json_index .. $_json_index + 3])));
-                               $_json_index += 3;
-                               $seen_slash = 0;
-                       } else {
-                               $val .= 'u';
-                       }
-               } else {
-                       $val .= $c;
-               }
-               $_json_index++;
-
-               #warn "string is $val";
-       }
-
-       return $val;
-}
-
-sub _json_parse_comment {
-       my $data = shift;
-
-       #warn "parse_comment";
-
-       if ($$data[$_json_index] eq '/') {
-               $_json_index++;
-               while (!($$data[$_json_index] eq "\n")) { $_json_index++ }
-               $_json_index++;
-               return undef;
-       }
-
-       my $class = '';
-
-       if (join('',$$data[$_json_index .. $_json_index + 2]) eq '*--') {
-               $_json_index += 3;
-               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-               if ($$data[$_json_index] eq 'S') {
-                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-                       while ($$data[$_json_index] !~ /[-\s]+/o) {
-                               $class .= $$data[$_json_index];
-                               $_json_index++;
-                       }
-                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-               }
-       }
-
-       while ($$data[$_json_index] ne '/') { $_json_index++ };
-       $_json_index++;
-
-       return $class;
-}
-
-sub old_JSON2perl {
-       my ($class, $json) = @_;
-
-       if (!defined($json)) {
-               return undef;
-       }
-
-       $json =~ s/(?<!\\)\$/\\\$/gmo; # fixup $ for later
-       $json =~ s/(?<!\\)\@/\\\@/gmo; # fixup @ for later
-       $json =~ s/(?<!\\)\%/\\\%/gmo; # fixup % for later
-
-       my @casts;
-       my $casting_depth = 0;
-       my $current_cast;
-       my $element;
-       my $output = '';
-       while (($json,$element) = _JSON_regex($json)) {
-
-               last unless ($element);
-
-               if ($element eq 'null') {
-                       $output .= ' undef() ';
-                       next;
-               } elsif ($element =~ /^\/\*--\s*S\w*?\s+(\w+)\s*--\*\/$/) {
-                       my $hint = $1;
-                       if (exists $_class_map{hints}{$hint}) {
-                               $casts[$casting_depth] = $hint;
-                               $output .= ' bless(';
-                       }
-                       next;
-               } elsif ($element =~ /^\/\*/) {
-                       next;
-               } elsif ($element =~ /^\d/) {
-                       $output .= "do { JSON::number::new($element) }";
-                       next;
-               } elsif ($element eq '{' or $element eq '[') {
-                       $casting_depth++;
-               } elsif ($element eq '}' or $element eq ']') {
-                       $casting_depth--;
-                       my $hint = $casts[$casting_depth];
-                       $casts[$casting_depth] = undef;
-                       if (defined $hint and exists $_class_map{hints}{$hint}) {
-                               $output .= $element . ',"'. $_class_map{hints}{$hint}{name} . '")';
-                               next;
-                       }
-               } elsif ($element eq ':') {
-                       $output .= ' => ';
-                       next;
-               } elsif ($element eq 'true') {
-                       $output .= 'bless( {}, "JSON::bool::true")';
-                       next;
-               } elsif ($element eq 'false') {
-                       $output .= 'bless( {}, "JSON::bool::false")';
-                       next;
-               }
-               
-               $output .= $element;
-       }
-
-       return eval $output;
-}
-
-sub perl2JSON {
-       my ($class, $perl, $strict) = @_;
-
-       my $output = '';
-       if (!defined($perl)) {
-               $output = '' if $strict;
-               $output = 'null' unless $strict;
-       } elsif (ref($perl) and ref($perl) =~ /^JSON/) {
-               $output .= $perl;
-       } elsif ( ref($perl) && exists($_class_map{classes}{ref($perl)}) ) {
-               $output .= '/*--S '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
-               if (lc($_class_map{classes}{ref($perl)}{type}) eq 'hash') {
-                       my %hash =  %$perl;
-                       $output .= perl2JSON(undef,\%hash, $strict);
-               } elsif (lc($_class_map{classes}{ref($perl)}{type}) eq 'array') {
-                       my @array =  @$perl;
-                       $output .= perl2JSON(undef,\@array, $strict);
-               }
-               $output .= '/*--E '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
-       } elsif (ref($perl) and ref($perl) =~ /HASH/) {
-               $output .= '{';
-               my $c = 0;
-               for my $key (sort keys %$perl) {
-                       my $outkey = NFC($key);
-                       $output .= ',' if ($c); 
-
-                       $outkey =~ s{\\}{\\\\}sgo;
-                       $outkey =~ s/"/\\"/sgo;
-                       $outkey =~ s/\t/\\t/sgo;
-                       $outkey =~ s/\f/\\f/sgo;
-                       $outkey =~ s/\r/\\r/sgo;
-                       $outkey =~ s/\n/\\n/sgo;
-                       $outkey =~ s/([\x{0080}-\x{fffd}])/sprintf('\u%0.4x',ord($1))/sgoe;
-
-                       $output .= '"'.$outkey.'":'. perl2JSON(undef,$$perl{$key}, $strict);
-                       $c++;
-               }
-               $output .= '}';
-       } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
-               $output .= '[';
-               my $c = 0;
-               for my $part (@$perl) {
-                       $output .= ',' if ($c); 
-                       
-                       $output .= perl2JSON(undef,$part, $strict);
-                       $c++;
-               }
-               $output .= ']';
-       } elsif (ref($perl) and ref($perl) =~ /CODE/) {
-               $output .= perl2JSON(undef,$perl->(), $strict);
-       } elsif (ref($perl) and ("$perl" =~ /^([^=]+)=(\w+)/o)) {
-               my $type = $2;
-               my $name = $1;
-               JSON->register_class_hint(name => $name, hint => $name, type => lc($type));
-               $output .= perl2JSON(undef,$perl, $strict);
-       } else {
-               $perl = NFC($perl);
-               $perl =~ s{\\}{\\\\}sgo;
-               $perl =~ s/"/\\"/sgo;
-               $perl =~ s/\t/\\t/sgo;
-               $perl =~ s/\f/\\f/sgo;
-               $perl =~ s/\r/\\r/sgo;
-               $perl =~ s/\n/\\n/sgo;
-               $perl =~ s/([\x{0080}-\x{fffd}])/sprintf('\u%0.4x',ord($1))/sgoe;
-               if (length($perl) < 10 and $perl =~ /^(?:\+|-)?\d*\.?\d+$/o and $perl !~ /^(?:\+|-)?0\d+/o ) {
-                       $output = $perl;
-               } else {
-                       $output = '"'.$perl.'"';
-               }
-       }
-
-       return $output;
-}
-
-my $depth = 0;
-sub perl2prettyJSON {
-       my ($class, $perl, $nospace) = @_;
-       $perl ||= $class;
-
-       my $output = '';
-       if (!defined($perl)) {
-               $output = "   "x$depth unless($nospace);
-               $output .= 'null';
-       } elsif (ref($perl) and ref($perl) =~ /^JSON/) {
-               $output = "   "x$depth unless($nospace);
-               $output .= $perl;
-       } elsif ( ref($perl) && exists($_class_map{classes}{ref($perl)}) ) {
-               $depth++;
-               $output .= "\n";
-               $output .= "   "x$depth;
-               $output .= '/*--S '.$_class_map{classes}{ref($perl)}{hint}."--*/ ";
-               if (lc($_class_map{classes}{ref($perl)}{type}) eq 'hash') {
-                       my %hash =  %$perl;
-                       $output .= perl2prettyJSON(\%hash,undef,1);
-               } elsif (lc($_class_map{classes}{ref($perl)}{type}) eq 'array') {
-                       my @array =  @$perl;
-                       $output .= perl2prettyJSON(\@array,undef,1);
-               }
-               $output .= ' /*--E '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
-               $depth--;
-       } elsif (ref($perl) and ref($perl) =~ /HASH/) {
-               $output .= "   "x$depth unless ($nospace);
-               $output .= "{\n";
-               my $c = 0;
-               $depth++;
-               for my $key (sort keys %$perl) {
-                       $output .= ",\n" if ($c); 
-                       $output .= "   "x$depth;
-                       $output .= perl2prettyJSON($key)." : ".perl2prettyJSON($$perl{$key}, undef, 1);
-                       $c++;
-               }
-               $depth--;
-               $output .= "\n";
-               $output .= "   "x$depth;
-               $output .= '}';
-       } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
-               $output .= "   "x$depth unless ($nospace);
-               $output .= "[\n";
-               my $c = 0;
-               $depth++;
-               for my $part (@$perl) {
-                       $output .= ",\n" if ($c); 
-                       $output .= "   "x$depth;
-                       $output .= perl2prettyJSON($part);
-                       $c++;
-               }
-               $depth--;
-               $output .= "\n";
-               $output .= "   "x$depth;
-               $output .= "]";
-       } elsif (ref($perl) and ref($perl) =~ /CODE/) {
-               $output .= perl2prettyJSON(undef,$perl->(), $nospace);
-       } elsif (ref($perl) and "$perl" =~ /^([^=]+)=(\w{4,5})\(0x/) {
-               my $type = $2;
-               my $name = $1;
-               register_class_hint(undef, name => $name, hint => $name, type => lc($type));
-               $output .= perl2prettyJSON(undef,$perl);
-       } else {
-               $perl = NFC($perl);
-               $perl =~ s/\\/\\\\/sgo;
-               $perl =~ s/"/\\"/sgo;
-               $perl =~ s/\t/\\t/sgo;
-               $perl =~ s/\f/\\f/sgo;
-               $perl =~ s/\r/\\r/sgo;
-               $perl =~ s/\n/\\n/sgo;
-               $perl =~ s/([\x{0080}-\x{fffd}])/sprintf('\u%0.4x',ord($1))/sgoe;
-               $output .= "   "x$depth unless($nospace);
-               if (length($perl) < 10 and $perl =~ /^(?:\+|-)?\d*\.?\d+$/o and $perl !~ /^(?:\+|-)?0\d+/o ) {
-                       $output = $perl;
-               } else {
-                       $output = '"'.$perl.'"';
-               }
-       }
-
-       return $output;
-}
-
-1;
index 6c32af1..9b2017a 100644 (file)
@@ -1,10 +1,9 @@
 package OpenSRF::AppSession;
-use OpenSRF::DOM;
-#use OpenSRF::DOM::Element::userAuth;
 use OpenSRF::DomainObject::oilsMessage;
 use OpenSRF::DomainObject::oilsMethod;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use OpenSRF::Transport::PeerHandle;
+use OpenSRF::Utils::JSON;
 use OpenSRF::Utils::Logger qw(:level);
 use OpenSRF::Utils::SettingsClient;
 use OpenSRF::Utils::Config;
@@ -531,7 +530,7 @@ sub send {
                }
 
        } 
-       my $json = JSON->perl2JSON(\@doc);
+       my $json = OpenSRF::Utils::JSON->perl2JSON(\@doc);
        $logger->internal("AppSession sending doc: $json");
 
        $self->{peer_handle}->send( 
index 0b3f9b7..71e62a4 100644 (file)
@@ -10,7 +10,7 @@ use Data::Dumper;
 use Time::HiRes qw/time/;
 use OpenSRF::EX qw/:try/;
 use Carp;
-use JSON;
+use OpenSRF::Utils::JSON;
 #use OpenSRF::UnixServer;  # to get the server class from UnixServer::App
 
 sub DESTROY{};
@@ -148,7 +148,7 @@ sub handler {
                                                        for my $p (0 .. scalar(@{ $sig->{params} }) - 1 ) {
                                                                my $s = $sig->{params}->[$p];
                                                                my $a = $args[$p];
-                                                               if ($s->{class} && JSON->lookup_hint(ref $a) ne $s->{class}) {
+                                                               if ($s->{class} && OpenSRF::Utils::JSON->lookup_hint(ref $a) ne $s->{class}) {
                                                                        die "Incorrect param class at position $p : should be a '$$s{class}'";
                                                                } elsif ($s->{type}) {
                                                                        if (lc($s->{type}) eq 'object' && $a !~ /HASH/o) {
@@ -225,7 +225,7 @@ sub handler {
                                                                for my $p (0 .. scalar(@{ $sig->{params} }) - 1 ) {
                                                                        my $s = $sig->{params}->[$p];
                                                                        my $a = $args[$p];
-                                                                       if ($s->{class} && JSON->lookup_hint(ref $a) ne $s->{class}) {
+                                                                       if ($s->{class} && OpenSRF::Utils::JSON->lookup_hint(ref $a) ne $s->{class}) {
                                                                                die "Incorrect param class at position $p : should be a '$$s{class}'";
                                                                        } elsif ($s->{type}) {
                                                                                if (lc($s->{type}) eq 'object' && $a !~ /HASH/o) {
@@ -393,7 +393,7 @@ sub register_method {
                ($args{object_hint} = $args{package}) =~ s/::/_/go;
        }
 
-       JSON->register_class_hint( name => $args{package}, hint => $args{object_hint}, type => "hash" );
+       OpenSRF::Utils::JSON->register_class_hint( name => $args{package}, hint => $args{object_hint}, type => "hash" );
 
        $_METHODS[$args{api_level}]{$args{api_name}} = bless \%args => $app;
 
index eed993a..1bc99ef 100644 (file)
@@ -3,7 +3,6 @@ use base qw/OpenSRF::Application/;
 use OpenSRF::Application;
 use OpenSRF::Utils::Logger qw/:level/;
 use OpenSRF::DomainObject::oilsResponse;
-#use OpenSRF::DomainObject::oilsPrimitive;
 use OpenSRF::EX qw/:try/;
 use strict;
 use warnings;
index eb90345..6cdc78c 100644 (file)
@@ -1,9 +1,8 @@
 package OpenSRF::Application::Demo::MathDB;
-use JSON;
+use OpenSRF::Utils::JSON;
 use base qw/OpenSRF::Application/;
 use OpenSRF::Application;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
-#use OpenSRF::DomainObject::oilsPrimitive;
 use OpenSRF::Utils::Logger qw/:level/;
 use strict;
 use warnings;
@@ -20,7 +19,7 @@ sub add_1 {
        my $n1 = shift; 
        my $n2 = shift;
        my $a = $n1 + $n2;
-       return JSON::number->new($a);
+       return OpenSRF::Utils::JSON::number->new($a);
 }
 
 __PACKAGE__->register_method( method => 'sub_1', api_name => 'dbmath.sub' );
@@ -31,7 +30,7 @@ sub sub_1 {
        my $n1 = shift; 
        my $n2 = shift;
        my $a = $n1 - $n2;
-       return JSON::number->new($a);
+       return OpenSRF::Utils::JSON::number->new($a);
 }
 
 __PACKAGE__->register_method( method => 'mult_1', api_name => 'dbmath.mult' );
@@ -42,7 +41,7 @@ sub mult_1 {
        my $n1 = shift; 
        my $n2 = shift;
        my $a = $n1 * $n2;
-       return JSON::number->new($a);
+       return OpenSRF::Utils::JSON::number->new($a);
 }
 
 __PACKAGE__->register_method( method => 'div_1', api_name => 'dbmath.div' );
@@ -53,7 +52,7 @@ sub div_1 {
        my $n1 = shift; 
        my $n2 = shift;
        my $a = $n1 / $n2;
-       return JSON::number->new($a);
+       return OpenSRF::Utils::JSON::number->new($a);
 }
 
 1;
index 1099dba..b8b291f 100644 (file)
@@ -6,7 +6,7 @@ use OpenSRF::Utils::SettingsClient;
 use OpenSRF::EX qw/:try/;
 use OpenSRF::Utils qw/:common/;
 use OpenSRF::Utils::Logger;
-use JSON;
+use OpenSRF::Utils::JSON;
 use DBI;
 
 use vars qw/$dbh $log $default_expire_time/;
@@ -227,7 +227,7 @@ sub add_item {
                        $dbh->do('DELETE FROM storage WHERE name_id = ?;', {}, $name_id);
                }
 
-               $dbh->do('INSERT INTO storage (name_id,value) VALUES (?,?);', {}, $name_id, JSON->perl2JSON($value));
+               $dbh->do('INSERT INTO storage (name_id,value) VALUES (?,?);', {}, $name_id, OpenSRF::Utils::JSON->perl2JSON($value));
 
                _flush_by_name($name);
 
@@ -344,7 +344,7 @@ sub pop_queue {
 
                _flush_by_name($name);
 
-               return JSON->JSON2perl( $value->[1] );
+               return OpenSRF::Utils::JSON->JSON2perl( $value->[1] );
        } catch Error with {
                #my $e = shift;
                #return $e;
@@ -377,7 +377,7 @@ sub peek_slot {
        
        my $values = $dbh->selectall_arrayref("SELECT value FROM storage WHERE name_id = ? ORDER BY id $order;", {}, $name_id);
 
-       $client->respond( JSON->JSON2perl( $_->[0] ) ) for (@$values);
+       $client->respond( OpenSRF::Utils::JSON->JSON2perl( $_->[0] ) ) for (@$values);
 
        _flush_by_name($name);
        return undef;
@@ -407,7 +407,7 @@ sub store_size {
 
        my $value = $dbh->selectcol_arrayref('SELECT SUM(LENGTH(value)) FROM storage WHERE name_id = ?;', {}, $name_id);
 
-       return JSON->JSON2perl( $value->[0] );
+       return OpenSRF::Utils::JSON->JSON2perl( $value->[0] );
 }
 __PACKAGE__->register_method(
        api_name => 'opensrf.persist.queue.size',
@@ -436,7 +436,7 @@ sub store_depth {
 
        my $value = $dbh->selectcol_arrayref('SELECT COUNT(*) FROM storage WHERE name_id = ?;', {}, $name_id);
 
-       return JSON->JSON2perl( $value->[0] );
+       return OpenSRF::Utils::JSON->JSON2perl( $value->[0] );
 }
 __PACKAGE__->register_method(
        api_name => 'opensrf.persist.queue.length',
@@ -465,7 +465,7 @@ sub shift_stack {
 
                _flush_by_name($name);
 
-               return JSON->JSON2perl( $value->[1] );
+               return OpenSRF::Utils::JSON->JSON2perl( $value->[1] );
        } catch Error with {
                my $e = shift;
                return undef;
@@ -498,7 +498,7 @@ sub get_object {
 
                _flush_by_name($name);
 
-               return JSON->JSON2perl( $value->[1] );
+               return OpenSRF::Utils::JSON->JSON2perl( $value->[1] );
        } catch Error with {
                return undef;
        };
diff --git a/src/perlmods/OpenSRF/DOM.pm b/src/perlmods/OpenSRF/DOM.pm
deleted file mode 100644 (file)
index 8ddb095..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-use XML::LibXML;
-use OpenSRF::Utils::Logger qw(:level);
-
-package XML::LibXML::Element;
-use OpenSRF::EX;
-
-sub AUTOLOAD {
-       my $self = shift;
-       (my $name = $AUTOLOAD) =~ s/.*://;   # strip fully-qualified portion
-
-       ### Check for recursion
-       my $calling_method = (caller(1))[3];
-       my @info = caller(1);
-
-       if( @info ) {
-               if ($info[0] =~ /AUTOLOAD/) { @info = caller(2); }
-       }
-       unless( @info ) { @info = caller(); }
-       if( $calling_method  and $calling_method eq "XML::LibXML::Element::AUTOLOAD" ) {
-               throw OpenSRF::EX::PANIC ( "RECURSION! Caller [ @info ] | Object [ ".ref($self)." ]\n ** Trying to call $name", ERROR );
-       }
-       ### Check for recursion
-       
-       #OpenSRF::Utils::Logger->debug( "Autoloading method for DOM: $AUTOLOAD on ".$self->toString, INTERNAL );
-
-       my $new_node = OpenSRF::DOM::upcast($self);
-       OpenSRF::Utils::Logger->debug( "Autoloaded to: ".ref($new_node), INTERNAL );
-
-       return $new_node->$name(@_);
-}
-
-
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM;
-use base qw/XML::LibXML OpenSRF/;
-
-our %_NAMESPACE_MAP = (
-       'http://open-ils.org/xml/namespaces/oils_v1' => 'oils',
-);
-
-our $_one_true_parser;
-
-sub new {
-       my $self = shift;
-       return $_one_true_parser if (defined $_one_true_parser);
-       $_one_true_parser = $self->SUPER::new(@_);
-       $_one_true_parser->keep_blanks(0);
-       $XML::LibXML::skipXMLDeclaration = 0;
-       return $_one_true_parser = $self->SUPER::new(@_);
-}
-
-sub createDocument {
-       my $self = shift;
-
-       # DOM API: createDocument(namespaceURI, qualifiedName, doctype?)
-       my $doc = XML::LibXML::Document->new("1.0", "UTF-8");
-       my $el = $doc->createElement('root');
-
-       $el->setNamespace('http://open-ils.org/xml/namespaces/oils_v1', 'oils', 1);
-       $doc->setDocumentElement($el);
-
-       return $doc;
-}
-
-my %_loaded_classes;
-sub upcast {
-       my $node = shift;
-       return undef unless $node;
-
-       my ($ns,$tag) = split ':' => $node->nodeName;
-
-       return $node unless ($ns eq 'oils');
-
-       my $class = "OpenSRF::DOM::Element::$tag";
-       unless (exists $_loaded_classes{$class}) {
-               $class->use;
-               $_loaded_classes{$class} = 1;
-       }
-       if ($@) {
-               OpenSRF::Utils::Logger->error("Couldn't use $class! $@");
-       }
-
-       #OpenSRF::Utils::Logger->debug("Upcasting ".$node->toString." to $class", INTERNAL);
-
-       return bless $node => $class;
-}
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Node;
-use base 'XML::LibXML::Node';
-
-sub new {
-       my $class = shift;
-       return bless $class->SUPER::new(@_) => $class;
-}
-
-sub childNodes {
-       my $self = shift;
-       my @children = $self->_childNodes();
-       return wantarray ? @children : OpenSRF::DOM::NodeList->new( @children );
-}
-
-sub attributes {
-       my $self = shift;
-       my @attr = $self->_attributes();
-       return wantarray ? @attr : OpenSRF::DOM::NamedNodeMap->new( @attr );
-}
-
-sub findnodes {
-       my ($node, $xpath) = @_;
-       my @nodes = $node->_findnodes($xpath);
-       if (wantarray) {
-               return @nodes;
-       } else {
-               return OpenSRF::DOM::NodeList->new(@nodes);
-       }
-}
-
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::NamedNodeMap;
-use base 'XML::LibXML::NamedNodeMap';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::NodeList;
-use base 'XML::LibXML::NodeList';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Element;
-use base 'XML::LibXML::Element';
-
-sub new {
-       my $class = shift;
-
-       # magically create the element (tag) name, or build a blank element
-       (my $name = $class) =~ s/^OpenSRF::DOM::Element:://;
-       if ($name) {
-               $name = "oils:$name";
-       } else {
-               undef $name;
-       }
-
-       my $self = $class->SUPER::new($name);
-
-       my %attrs = @_;
-       for my $aname (keys %attrs) {
-               $self->setAttribute($aname, $attrs{$aname});
-       }
-
-       return $self;
-}
-
-sub getElementsByTagName {
-    my ( $node , $name ) = @_;
-        my $xpath = "descendant::$name";
-    my @nodes = $node->_findnodes($xpath);
-        return wantarray ? @nodes : OpenSRF::DOM::NodeList->new(@nodes);
-}
-
-sub  getElementsByTagNameNS {
-    my ( $node, $nsURI, $name ) = @_;
-    my $xpath = "descendant::*[local-name()='$name' and namespace-uri()='$nsURI']";
-    my @nodes = $node->_findnodes($xpath);
-    return wantarray ? @nodes : OpenSRF::DOM::NodeList->new(@nodes);
-}
-
-sub getElementsByLocalName {
-    my ( $node,$name ) = @_;
-    my $xpath = "descendant::*[local-name()='$name']";
-    my @nodes = $node->_findnodes($xpath);
-    return wantarray ? @nodes : OpenSRF::DOM::NodeList->new(@nodes);
-}
-
-sub getChildrenByLocalName {
-    my ( $node,$name ) = @_;
-    my $xpath = "./*[local-name()='$name']";
-    my @nodes = $node->_findnodes($xpath);
-    return @nodes;
-}
-
-sub getChildrenByTagName {
-    my ( $node, $name ) = @_;
-    my @nodes = grep { $_->nodeName eq $name } $node->childNodes();
-    return @nodes;
-}
-
-sub getChildrenByTagNameNS {
-    my ( $node, $nsURI, $name ) = @_;
-    my $xpath = "*[local-name()='$name' and namespace-uri()='$nsURI']";
-    my @nodes = $node->_findnodes($xpath);
-    return @nodes;
-}
-
-sub appendWellBalancedChunk {
-    my ( $self, $chunk ) = @_;
-
-    my $local_parser = OpenSRF::DOM->new();
-    my $frag = $local_parser->parse_xml_chunk( $chunk );
-
-    $self->appendChild( $frag );
-}
-
-package OpenSRF::DOM::Element::root;
-use base 'OpenSRF::DOM::Element';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Text;
-use base 'XML::LibXML::Text';
-
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Comment;
-use base 'XML::LibXML::Comment';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::CDATASection;
-use base 'XML::LibXML::CDATASection';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Document;
-use base 'XML::LibXML::Document';
-
-sub empty {
-       my $self = shift;
-       return undef unless (ref($self));
-       $self->documentElement->removeChild($_) for $self->documentElement->childNodes;
-       return $self;
-}
-
-sub new {
-       my $class = shift;
-       return bless $class->SUPER::new(@_) => $class;
-}
-
-sub getElementsByTagName {
-       my ( $doc , $name ) = @_;
-       my $xpath = "descendant-or-self::node()/$name";
-       my @nodes = $doc->_findnodes($xpath);
-       return wantarray ? @nodes : OpenSRF::DOM::NodeList->new(@nodes);
-}
-
-sub  getElementsByTagNameNS {
-       my ( $doc, $nsURI, $name ) = @_;
-       my $xpath = "descendant-or-self::*[local-name()='$name' and namespace-uri()='$nsURI']";
-       my @nodes = $doc->_findnodes($xpath);
-       return wantarray ? @nodes : OpenSRF::DOM::NodeList->new(@nodes);
-}
-
-sub getElementsByLocalName {
-       my ( $doc,$name ) = @_;
-       my $xpath = "descendant-or-self::*[local-name()='$name']";
-       my @nodes = $doc->_findnodes($xpath);
-       return wantarray ? @nodes : OpenSRF::DOM::NodeList->new(@nodes);
-}
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::DocumentFragment;
-use base 'XML::LibXML::DocumentFragment';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Attr;
-use base 'XML::LibXML::Attr';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Dtd;
-use base 'XML::LibXML::Dtd';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::PI;
-use base 'XML::LibXML::PI';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Namespace;
-use base 'XML::LibXML::Namespace';
-
-sub isEqualNode {
-       my ( $self, $ref ) = @_;
-       if ( $ref->isa("XML::LibXML::Namespace") ) {
-               return $self->_isEqual($ref);
-       }
-       return 0;
-}
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Schema;
-use base 'XML::LibXML::Schema';
-
-1;
diff --git a/src/perlmods/OpenSRF/DOM/Element/domainObject.pm b/src/perlmods/OpenSRF/DOM/Element/domainObject.pm
deleted file mode 100644 (file)
index 4b98512..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-package OpenSRF::DOM::Element::domainObject;
-use strict; use warnings;
-use base 'OpenSRF::DOM::Element';
-use OpenSRF::DOM;
-use OpenSRF::DOM::Element::domainObjectAttr;
-use OpenSRF::Utils::Logger qw(:level);
-use OpenSRF::EX qw(:try);
-use Carp;
-#use OpenSRF::DomainObject::oilsPrimitive;
-#use OpenSRF::DomainObject::oilsResponse;
-use vars qw($AUTOLOAD);
-
-sub AUTOLOAD {
-       my $self = shift;
-       (my $name = $AUTOLOAD) =~ s/.*://;   # strip fully-qualified portion
-
-       return class($self) if ($name eq 'class');
-       if ($self->can($name)) {
-               return $self->$name(@_);
-       }
-
-       if (1) {
-               ### Check for recursion
-               my $calling_method = (caller(1))[3];
-               my @info = caller(1);
-
-               if( @info ) {
-                       if ($info[0] =~ /AUTOLOAD/) { @info = caller(2); }
-               }
-               unless( @info ) { @info = caller(); }
-
-               if( $calling_method  and $calling_method eq "OpenSRF::DOM::Element::domainObject::AUTOLOAD" ) {
-                       warn Carp::cluck;
-                       throw OpenSRF::EX::PANIC ( "RECURSION! Caller [ @info[0..2] ] | Object [ ".ref($self)." ]\n ** Trying to call $name", ERROR );
-               }
-               ### Check for recursion
-       }
-
-        my @args = @_;
-       my $meth = class($self).'::'.$name;
-
-       try {
-               return $self->$meth(@args);
-       } catch Error with {
-               my $e = shift;
-               if( $e ) {
-                       OpenSRF::Utils::Logger->error( $@ . $e);
-               } else {
-                       OpenSRF::Utils::Logger->error( $@ );
-               }
-               die $@;
-       };
-
-
-       my $node = OpenSRF::DOM::Element::domainObject::upcast($self);
-       OpenSRF::Utils::Logger->debug( "Autoloaded to: ".ref($node), INTERNAL );
-
-       return $node->$name(@_);
-}
-
-sub downcast {
-       my $obj = shift;
-       return bless $obj => 'XML::LibXML::Element';
-}
-
-sub upcast {
-       my $self = shift;
-       return bless $self => class($self);
-}
-
-sub new {
-       my $class = shift;
-       my $type = shift;
-       my $obj = $class->SUPER::new( name => $type );
-       while (@_) {
-               my ($attr,$val) = (shift,shift);
-               last unless ($attr and $val);
-               $obj->addAttr( $attr, $val );
-               #$obj->appendChild( OpenSRF::DOM::Element::domainObjectAttr->new($attr, $val) );
-       }
-       return $obj;
-}
-
-sub class {
-       my $self = shift;
-       return 'OpenSRF::DomainObject::'.$self->getAttribute('name');
-}
-
-sub base_type {
-       my $self = shift;
-        return $self->getAttribute('name');
-}
-
-sub addAttr {
-       my $self = shift;
-       $self->appendChild( $_ ) for OpenSRF::DOM::Element::domainObjectAttr->new(@_);
-       return $self;
-}
-
-sub attrNode {
-       my $self = shift;
-       my $type = shift;
-       return (grep { $_->getAttribute('name') eq $type } $self->getChildrenByTagName("oils:domainObjectAttr"))[0];
-}
-
-sub attrHash {
-       my $self = shift;
-       my %attrs = map { ( $_->getAttribute('name') => $_->getAttribute('value') ) } $self->getChildrenByTagName('oils:domainObjectAttr');
-
-       return \%attrs;
-}
-
-sub attrValue {
-       my $self = shift;
-       return $self->attrHash->{shift};
-}
-
-1;
diff --git a/src/perlmods/OpenSRF/DOM/Element/domainObjectAttr.pm b/src/perlmods/OpenSRF/DOM/Element/domainObjectAttr.pm
deleted file mode 100644 (file)
index fbdc28e..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-package OpenSRF::DOM::Element::domainObjectAttr;
-use base 'OpenSRF::DOM::Element';
-
-sub new {
-       my $class = shift;
-       my @nodes;
-       while (@_) {
-               my ($name,$val) = (shift,shift);
-               push @nodes, $class->SUPER::new(name => $name, value => $val);
-       }
-       return @nodes if (wantarray);
-       return $nodes[0];
-}
-
-1;
diff --git a/src/perlmods/OpenSRF/DOM/Element/domainObjectCollection.pm b/src/perlmods/OpenSRF/DOM/Element/domainObjectCollection.pm
deleted file mode 100644 (file)
index 264c435..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-package OpenSRF::DOM::Element::domainObjectCollection;
-use base 'OpenSRF::DOM::Element';
-use OpenSRF::DOM::Element::domainObjectAttr;
-use OpenSRF::EX;
-
-sub AUTOLOAD {
-       my $self = CORE::shift;
-       (my $name = $AUTOLOAD) =~ s/.*://;   # strip fully-qualified portion
-
-       return  class($self) if ($name eq 'class');
-
-       my @args = @_;
-       my $meth = class($self).'::'.$name;
-
-       ### Check for recursion
-       my $calling_method = (caller(1))[3];
-       my @info = caller(1);
-
-       if( @info ) {
-               if ($info[0] =~ /AUTOLOAD/) { @info = caller(2); }
-       }
-       unless( @info ) { @info = caller(); }
-               if( $calling_method  and $calling_method eq "OpenSRF::DOM::Element::domainObjectCollection::AUTOLOAD" ) {
-               throw OpenSRF::EX::PANIC ( "RECURSION! Caller [ @info ] | Object [ ".ref($self)." ]\n ** Trying to call $name", ERROR );
-       }
-       ### Check for recursion
-
-       try {
-               return $self->$meth(@args);;
-       } catch Error with {
-               my $e = shift;
-               OpenSRF::Utils::Logger->error( $@ . $e);
-               die $@;
-       };
-
-       return upcast($self)->$name(@_);
-}
-
-sub downcast {
-       my $obj = CORE::shift;
-       return bless $obj => 'XML::LibXML::Element';
-}
-
-sub upcast {
-       my $self = CORE::shift;
-       return bless $self => class($self);
-}
-
-sub new {
-       my $class = CORE::shift;
-       my $type = CORE::shift;
-       my $obj = $class->SUPER::new( name => $type );
-       while ( my $val = shift) {
-               throw OpenSRF::EX::NotADomainObject
-                       if (ref $val and $val->nodeName !~ /^oils:domainObject/o);
-               $obj->appendChild( $val );
-       }
-       return $obj;
-}
-
-sub class {
-       my $self = shift;
-       return 'OpenSRF::DomainObjectCollection::'.$self->getAttribute('name');
-}
-
-sub base_type {
-       my $self = shift;
-       return $self->getAttribute('name');
-}
-
-sub pop { 
-       my $self = CORE::shift;
-       return $self->removeChild( $self->lastChild )->upcast;
-}
-
-sub push { 
-       my $self = CORE::shift;
-       my @args = @_;
-       for my $node (@args) {
-               #throw OpenSRF::EX::NotADomainObject ( "$_ must be a oils:domainOjbect*, it's a ".$_->nodeName )
-               #       unless ($_->nodeName =~ /^oils:domainObject/o);
-               
-               unless ($node->nodeName =~ /^oils:domainObject/o) {
-                       $node = OpenSRF::DomainObject::oilsScalar->new($node);
-               }
-
-               $self->appendChild( $node );
-       }
-}
-
-sub shift { 
-       my $self = CORE::shift;
-       return $self->removeChild( $self->firstChild )->upcast;
-}
-
-sub unshift { 
-       my $self = CORE::shift;
-       my @args = @_;
-       for (reverse @args) {
-               throw OpenSRF::EX::NotADomainObject
-                       unless ($_->nodeName =~ /^oils:domainObject/o);
-               $self->insertBefore( $_, $self->firstChild );
-       }
-}
-
-sub first {
-       my $self = CORE::shift;
-       return $self->firstChild->upcast;
-}
-
-sub list {
-       my $self = CORE::shift;
-       return map {(bless($_ => 'OpenSRF::DomainObject::'.$_->getAttribute('name')))} $self->childNodes;
-}
-
-1;
diff --git a/src/perlmods/OpenSRF/DOM/Element/params.pm b/src/perlmods/OpenSRF/DOM/Element/params.pm
deleted file mode 100644 (file)
index ee3755a..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-package OpenSRF::DOM::Element::params;
-use base 'OpenSRF::DOM::Element';
-
-1;
diff --git a/src/perlmods/OpenSRF/DomainObject.pm b/src/perlmods/OpenSRF/DomainObject.pm
deleted file mode 100644 (file)
index 4dc4258..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-package OpenSRF::DomainObject;
-use base 'OpenSRF::DOM::Element::domainObject';
-use OpenSRF::DOM;
-use OpenSRF::Utils::Logger qw(:level);
-use OpenSRF::DomainObject::oilsPrimitive;
-my $logger = "OpenSRF::Utils::Logger";
-
-=head1 NAME
-
-OpenSRF::DomainObject
-
-=head1 SYNOPSIS
-
-OpenSRF::DomainObject is an abstract base class.  It
-should not be used directly.  See C<OpenSRF::DomainObject::*>
-for details.
-
-=cut
-
-my $tmp_doc;
-
-sub object_castor {
-       my $self = shift;
-       my $node = shift;
-
-       return unless (defined $node);
-
-       if (ref($node) eq 'HASH') {
-               return new OpenSRF::DomainObject::oilsHash (%$node);
-       } elsif (ref($node) eq 'ARRAY') {
-               return new OpenSRF::DomainObject::oilsArray (@$node);
-       }
-
-       return $node;
-}
-
-sub native_castor {
-       my $self = shift;
-       my $node = shift;
-
-       return unless (defined $node);
-
-       if ($node->nodeType == 3) {
-               return $node->nodeValue;
-       } elsif ($node->nodeName =~ /domainObject/o) {
-               return $node->tie_me if ($node->class->can('tie_me'));
-       }
-       return $node;
-}
-
-sub new {
-       my $class = shift;
-       $class = ref($class) || $class;
-
-       (my $type = $class) =~ s/^.+://o;
-
-       $tmp_doc ||= OpenSRF::DOM->createDocument;
-       my $dO = OpenSRF::DOM::Element::domainObject->new( $type, @_ );
-
-       $tmp_doc->documentElement->appendChild($dO);
-
-       return $dO;
-}
-
-sub _attr_get_set {
-       my $self = shift;
-       my $part = shift;
-
-       my $node = $self->attrNode($part);
-
-       if (defined(my $new_value = shift)) {
-               if (defined $node) {
-                       my $old_val = $node->getAttribute( "value" );
-                       $node->setAttribute(value => $new_value);
-                       return $old_val;
-               } else {
-                       $self->addAttr( $part => $new_value );
-                       return $new_value;
-               }
-       } elsif ( $node ) {
-               return $node->getAttribute( "value" );
-       }
-}
-
-1;
index 56fa9d3..1374e28 100644 (file)
@@ -1,18 +1,18 @@
 package OpenSRF::DomainObject::oilsMessage;
-use JSON;
+use OpenSRF::Utils::JSON;
 use OpenSRF::AppSession;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use OpenSRF::Utils::Logger qw/:level/;
 use warnings; use strict;
 use OpenSRF::EX qw/:try/;
 
-JSON->register_class_hint(hint => 'osrfMessage', name => 'OpenSRF::DomainObject::oilsMessage', type => 'hash');
+OpenSRF::Utils::JSON->register_class_hint(hint => 'osrfMessage', name => 'OpenSRF::DomainObject::oilsMessage', type => 'hash');
 
 sub toString {
        my $self = shift;
        my $pretty = shift;
-       return JSON->perl2prettyJSON($self) if ($pretty);
-       return JSON->perl2JSON($self);
+       return OpenSRF::Utils::JSON->perl2prettyJSON($self) if ($pretty);
+       return OpenSRF::Utils::JSON->perl2JSON($self);
 }
 
 sub new {
index 6c81902..f83727b 100644 (file)
@@ -1,13 +1,13 @@
 package OpenSRF::DomainObject::oilsMethod;
 
-use JSON;
-JSON->register_class_hint(hint => 'osrfMethod', name => 'OpenSRF::DomainObject::oilsMethod', type => 'hash');
+use OpenSRF::Utils::JSON;
+OpenSRF::Utils::JSON->register_class_hint(hint => 'osrfMethod', name => 'OpenSRF::DomainObject::oilsMethod', type => 'hash');
 
 sub toString {
        my $self = shift;
        my $pretty = shift;
-       return JSON->perl2prettyJSON($self) if ($pretty);
-       return JSON->perl2JSON($self);
+       return OpenSRF::Utils::JSON->perl2prettyJSON($self) if ($pretty);
+       return OpenSRF::Utils::JSON->perl2JSON($self);
 }
 
 sub new {
diff --git a/src/perlmods/OpenSRF/DomainObject/oilsMultiSearch.pm b/src/perlmods/OpenSRF/DomainObject/oilsMultiSearch.pm
deleted file mode 100644 (file)
index fda4523..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-package OpenSRF::DomainObjectCollection::oilsMultiSearch;
-use OpenSRF::DomainObjectCollection;
-use OpenSRF::DomainObject::oilsPrimitive;
-use OpenSRF::DomainObject::oilsSearch;
-use OpenSRF::DOM::Element::searchCriteria;
-use OpenSRF::DOM::Element::searchCriterium;
-use base 'OpenSRF::DomainObjectCollection::oilsHash';
-
-sub new {
-       my $class = shift;
-       my %args = @_;
-
-       $class = ref($class) || $class;
-
-       my $self = $class->SUPER::new;
-
-       tie my %hash, 'OpenSRF::DomainObjectCollection::oilsHash', $self;
-
-       $self->set( bind_count  => 1 );
-       $self->set( searches    => new OpenSRF::DomainObjectCollection::oilsHash );
-       $self->set( relators    => new OpenSRF::DomainObjectCollection::oilsArray );
-       $self->set( fields      => new OpenSRF::DomainObjectCollection::oilsArray );
-       $self->set( group_by    => new OpenSRF::DomainObjectCollection::oilsArray );
-       $self->set( order_by    => new OpenSRF::DomainObjectCollection::oilsArray );
-       
-       return $self;
-}
-
-sub add_subsearch {
-       my $self = shift;
-       my $alias = shift;
-       my $search = shift;
-       my $relator = shift;
-       
-       $search = OpenSRF::DomainObject::oilsSearch->new($search) if (ref($search) eq 'ARRAY');
-
-       $self->searches->set( $alias => $search );
-       
-       if ($self->searches->size > 1) {
-               throw OpenSRF::EX::InvalidArg ('You need to pass a relator searchCriterium')
-                       unless (defined $relator);
-       }
-
-       $relator = OpenSRF::DOM::Element::searchCriterium->new( @$relator )
-               if (ref($relator) eq 'ARRAY');
-
-       $self->relators->push( $relator ) if (defined $relator);
-
-       return $self;
-}
-
-sub relators {
-       return $_[0]->_accessor('relators');
-}
-
-sub searches {
-       return $_[0]->_accessor('searches');
-}
-
-sub fields {
-       my $self = shift;
-       my @parts = @_;
-       if (@parts) {
-               $self->set( fields => OpenSRF::DomainObjectCollection::oilsArray->new(@_) );
-       }
-       return $self->_accessor('fields')->list;
-}
-
-sub format {
-       $_[0]->set( format => $_[1] ) if (defined $_[1]);
-       return $_[0]->_accessor('format');
-}
-
-sub limit {
-       $_[0]->set( limit => $_[1] ) if (defined $_[1]);
-       return $_[0]->_accessor('limit');
-}
-
-sub offset {
-       $_[0]->set( offset => $_[1] ) if (defined $_[1]);
-       return $_[0]->_accessor('offset');
-}
-
-sub chunk_key {
-       $_[0]->set( chunk_key => $_[1] ) if (defined $_[1]);
-       return $_[0]->_accessor('chunk_key');
-}
-
-sub order_by {
-       my $self = shift;
-       my @parts = @_;
-       if (@parts) {
-               $self->set( order_by => OpenSRF::DomainObjectCollection::oilsArray->new(@_) );
-       }
-       return $self->_accessor('order_by')->list;
-}
-
-sub group_by {
-       my $self = shift;
-       my @parts = @_;
-       if (@parts) {
-               $self->set( group_by => OpenSRF::DomainObjectCollection::oilsArray->new(@_) );
-       }
-       return $self->_accessor('group_by')->list;
-}
-
-sub SQL_select_list {
-       my $self = shift;
-
-       if (my $sql = $self->_accessor('sql_select_list')) {
-               return $sql;
-       }
-
-       $self->set( sql_select_list => 'SELECT '.join(', ', $self->fields) ) if defined($self->fields);
-       return $self->_accessor('sql_select_list');
-}
-
-sub SQL_group_by {
-       my $self = shift;
-
-       if (my $sql = $self->_accessor('sql_group_by')) {
-               return $sql;
-       }
-
-       $self->set( sql_group_by => 'GROUP BY '.join(', ', $self->group_by) ) if defined($self->group_by);
-       return $self->_accessor('sql_group_by');
-}
-
-sub SQL_order_by {
-       my $self = shift;
-
-       if (my $sql = $self->_accessor('sql_order_by')) {
-               return $sql;
-       }
-
-       $self->set( sql_order_by => 'ORDER BY '.join(', ', $self->order_by) ) if defined($self->order_by);
-       return $self->_accessor('sql_order_by');
-}
-
-sub SQL_offset {
-       my $self = shift;
-
-       if (my $sql = $self->_accessor('sql_offset')) {
-               return $sql;
-       }
-
-       $self->set( sql_offset => 'OFFSET '.$self->offset ) if defined($self->offset);
-       return $self->_accessor('sql_offset');
-}
-
-sub SQL_limit {
-       my $self = shift;
-
-       if (my $sql = $self->_accessor('sql_limit')) {
-               return $sql;
-       }
-
-       $self->set( sql_limit => 'LIMIT '.$self->limit ) if defined($self->limit);
-       return $self->_accessor('sql_limit');
-}
-
-sub toSQL {
-       my $self = shift;
-
-       my $SQL = $self->SQL_select_list.' FROM ';
-
-       my @subselects;
-       for my $search ( $self->searches->keys ) {
-               push @subselects, '('.$self->searches->_accessor($search)->toSQL.') '.$search;
-       }
-       $SQL .= join(', ', @subselects).' WHERE ';
-
-       my @relators;
-       for my $rel ( $self->relators->list ) {
-               push @relators, $rel->value->toSQL( no_quote => 1 );
-       }
-       $SQL .= join(' AND ', @relators).' ';
-       $SQL .= join ' ', ($self->SQL_group_by, $self->SQL_order_by, $self->SQL_limit, $self->SQL_offset);
-
-       return $SQL;
-}
-
-#this is just to allow DomainObject to "upcast" nicely
-package OpenSRF::DomainObject::oilsMultiSearch;
-use base OpenSRF::DomainObjectCollection::oilsMultiSearch;
-1;
diff --git a/src/perlmods/OpenSRF/DomainObject/oilsPrimitive.pm b/src/perlmods/OpenSRF/DomainObject/oilsPrimitive.pm
deleted file mode 100644 (file)
index bf9507a..0000000
+++ /dev/null
@@ -1,623 +0,0 @@
-package OpenSRF::DomainObject::oilsScalar;
-use base 'OpenSRF::DomainObject';
-use OpenSRF::DomainObject;
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsScalar
-
-=head1 SYNOPSIS
-
-  use OpenSRF::DomainObject::oilsScalar;
-
-  my $text = OpenSRF::DomainObject::oilsScalar->new( 'a string or number' );
-  $text->value( 'replacement value' );
-  print "$text"; # stringify
-
-   ...
-
-  $text->value( 1 );
-  if( $text ) { # boolify
-
-   ...
-
-  $text->value( rand() * 1000 );
-  print 10 + $text; # numify
-
-    Or, using the TIE interface:
-
-  my $scalar;
-  my $real_object = tie($scalar, 'OpenSRF::DomainObject::oilsScalar', "a string to store...");
-
-  $scalar = "a new string";
-  print $scalar . "\n";
-  print $real_object->toString . "\n";
-
-=head1 METHODS
-
-=head2 OpenSRF::DomainObject::oilsScalar->value( [$new_value] )
-
-=over 4
-
-Sets or gets the value of the scalar.  As above, this can be specified
-as a build attribute as well as added to a prebuilt oilsScalar object.
-
-=back
-
-=cut
-
-use overload '""'   => sub { return ''.$_[0]->value };
-use overload '0+'   => sub { return int($_[0]->value) };
-use overload '<=>'   => sub { return int($_[0]->value) <=> $_[1] };
-use overload 'bool' => sub { return 1 if ($_[0]->value); return 0 };
-
-sub new {
-       my $class = shift;
-       $class = ref($class) || $class;
-
-       my $value = shift;
-
-       return $value
-               if (    defined $value and
-                       ref $value and $value->can('base_type') and
-                       UNIVERSAL::isa($value->class, __PACKAGE__) and
-                       !scalar(@_)
-               );
-
-       my $self = $class->SUPER::new;
-
-       if (ref($value) and ref($value) eq 'SCALAR') {
-               $self->value($$value);
-               tie( $$value, ref($self->upcast), $self);
-       } else {
-               $self->value($value) if (defined $value);
-       }
-
-       return $self;
-}
-
-sub TIESCALAR {
-       return CORE::shift()->new(@_);
-}
-
-sub value {
-       my $self = shift;
-       my $value = shift;
-
-       if ( defined $value ) {
-               $self->removeChild($_) for ($self->childNodes);
-               if (ref($value) && $value->isa('XML::LibXML::Node')) {
-                       #throw OpenSRF::EX::NotADomainObject
-                       #       unless ($value->nodeName =~ /^oils:domainObject/o);
-                       $self->appendChild($value);
-               } elsif (defined $value) {
-                       $self->appendText( ''.$value );
-               }
-
-               return $value
-       } else {
-               $value = $self->firstChild;
-               if ($value) {
-                       if ($value->nodeType == 3) {
-                               return $value->textContent;
-                       } else {
-                               return $value;
-                       }
-               }
-               return undef;
-       }
-}
-
-sub FETCH { $_[0]->value }
-sub STORE { $_[0]->value($_[1]) }
-
-package OpenSRF::DomainObject::oilsPair;
-use base 'OpenSRF::DomainObject::oilsScalar';
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsPair
-
-=head1 SYNOPSIS
-
-  use OpenSRF::DomainObject::oilsPair;
-
-  my $pair = OpenSRF::DomainObject::oilsPair->new( 'key_for_pair' => 'a string or number' );
-
-  $pair->key( 'replacement key' );
-  $pair->value( 'replacement value' );
-
-  print "$pair"; # stringify 'value'
-
-   ...
-
-  $pair->value( 1 );
-
-  if( $pair ) { # boolify
-
-   ...
-
-  $pair->value( rand() * 1000 );
-
-  print 10 + $pair; # numify 'value'
-
-=head1 ABSTRACT
-
-This class impliments a "named pair" object.  This is the basis for
-hash-type domain objects.
-
-=head1 METHODS
-
-=head2 OpenSRF::DomainObject::oilsPair->value( [$new_value] )
-
-=over 4
-
-Sets or gets the value of the pair.  As above, this can be specified
-as a build attribute as well as added to a prebuilt oilsPair object.
-
-=back
-
-=head2 OpenSRF::DomainObject::oilsPair->key( [$new_key] )
-
-=over 4
-
-Sets or gets the key of the pair.  As above, this can be specified
-as a build attribute as well as added to a prebuilt oilsPair object.
-This must be a perlish scalar; any string or number that is valid as the 
-attribute on an XML node will work.
-
-=back
-
-=cut
-
-use overload '""'   => sub { return ''.$_[0]->value };
-use overload '0+'   => sub { return int($_[0]->value) };
-use overload 'bool' => sub { return 1 if ($_[0]->value); return 0 };
-
-sub new {
-       my $class = shift;
-       my ($key, $value) = @_;
-
-       my $self = $class->SUPER::new($value);
-       $self->setAttribute( key => $key);
-
-       return $self;
-}
-
-sub key {
-       my $self = shift;
-       my $key = shift;
-
-       $self->setAttribute( key => $key) if ($key);
-       return $self->getAttribute( 'key' );
-}
-
-package OpenSRF::DomainObjectCollection::oilsArray;
-use base qw/OpenSRF::DomainObjectCollection Tie::Array/;
-use OpenSRF::DomainObjectCollection;
-
-=head1 NAME
-
-OpenSRF::DomainObjectCollection::oilsArray
-
-=head1 SYNOPSIS
-
-  use OpenSRF::DomainObject::oilsPrimitive;
-
-  my $collection = OpenSRF::DomainObjectCollection::oilsArray->new( $domain_object, $another_domain_object, ...);
-
-  $collection->push( 'appended value' );
-  $collection->unshift( 'prepended vaule' );
-  my $first = $collection->shift;
-  my $last = $collection->pop;
-
-   ...
-
-  my @values = $collection->list;
-
-    Or, using the TIE interface:
-
-  my @array;
-  my $real_object = tie(@array, 'OpenSRF::DomainObjectCollection::oilsArray', $domain, $objects, 'to', $store);
-
-      or to tie an existing $collection object
-
-  my @array;
-  tie(@array, 'OpenSRF::DomainObjectCollection::oilsArray', $collection);
-
-      or even....
-
-  my @array;
-  tie(@array, ref($collection), $collection);
-
-
-  $array[2] = $DomainObject; # replaces 'to' (which is now an OpenSRF::DomainObject::oilsScalar) above
-  delete( $array[3] ); # removes '$store' above.
-  my $size = scalar( @array );
-
-  print $real_object->toString;
-
-=head1 ABSTRACT
-
-This package impliments array-like domain objects.  A full tie interface
-is also provided.  If elements are passed in as strings (or numbers) they
-are turned into oilsScalar objects.  Any simple scalar or Domain Object may
-be stored in the array.
-
-=head1 METHODS
-
-=head2 OpenSRF::DomainObjectCollection::oilsArray->list()
-
-=over 4
-
-Returns the array of 'OpenSRF::DomainObject's that this collection contains.
-
-=back
-
-=cut
-
-sub tie_me {
-       my $class = shift;
-       $class = ref($class) || $class;
-       my $node = shift;
-       my @array;
-       tie @array, $class, $node;
-       return \@array;
-}
-
-# an existing DomainObjectCollection::oilsArray can now be tied
-sub TIEARRAY {
-       return CORE::shift()->new(@_);
-}
-
-sub new {
-       my $class = CORE::shift;
-       $class = ref($class) || $class;
-
-       my $first = CORE::shift;
-
-       return $first
-               if (    defined $first and
-                       ref $first and $first->can('base_type') and
-                       UNIVERSAL::isa($first->class, __PACKAGE__) and
-                       !scalar(@_)
-               );
-
-       my $self = $class->SUPER::new;
-
-       my @args = @_;
-       if (ref($first) and ref($first) eq 'ARRAY') {
-               push @args, @$first;
-               tie( @$first, ref($self->upcast), $self);
-       } else {
-               unshift @args, $first if (defined $first);
-       }
-
-       $self->STORE($self->FETCHSIZE, $_) for (@args);
-       return $self;
-}
-
-sub STORE {
-       my $self = CORE::shift;
-       my ($index, $value) = @_;
-
-       $value = OpenSRF::DomainObject::oilsScalar->new($value)
-               unless ( ref $value and $value->nodeName =~ /^oils:domainObject/o );
-
-       $self->_expand($index) unless ($self->EXISTS($index));
-
-       ($self->childNodes)[$index]->replaceNode( $value );
-
-       return $value->upcast;
-}
-
-sub push {
-       my $self = CORE::shift;
-       my @values = @_;
-       $self->STORE($self->FETCHSIZE, $_) for (@values);
-}
-
-sub pop {
-       my $self = CORE::shift;
-       my $node = $self->SUPER::pop;
-       if ($node) {
-               if ($node->base_type eq 'oilsScalar') {
-                       return $node->value;
-               }
-               return $node->upcast;
-       }
-}
-
-sub unshift {
-       my $self = CORE::shift;
-       my @values = @_;
-       $self->insertBefore($self->firstChild, $_ ) for (reverse @values);
-}
-
-sub shift {
-       my $self = CORE::shift;
-       my $node = $self->SUPER::shift;
-       if ($node) {
-               if ($node->base_type eq 'oilsScalar') {
-                       return $node->value;
-               }
-               return $node->upcast;
-       }
-}
-
-sub FETCH {
-       my $self = CORE::shift;
-       my $index = CORE::shift;
-       my $node =  ($self->childNodes)[$index]->upcast;
-       if ($node) {
-               if ($node->base_type eq 'oilsScalar') {
-                       return $node->value;
-               }
-               return $node->upcast;
-       }
-}
-
-sub size {
-       my $self = CORE::shift;
-       scalar($self->FETCHSIZE)
-}
-
-sub FETCHSIZE {
-       my $self = CORE::shift;
-       my @a = $self->childNodes;
-       return scalar(@a);
-}
-
-sub _expand {
-       my $self = CORE::shift;
-       my $count = CORE::shift;
-       my $size = $self->FETCHSIZE;
-       for ($size..$count) {
-               $self->SUPER::push( new OpenSRF::DomainObject::oilsScalar );
-       }
-}
-
-sub STORESIZE {
-       my $self = CORE::shift;
-       my $count = CORE::shift;
-       my $size = $self->FETCHSIZE - 1;
-
-       if (defined $count and $count != $size) {
-               if ($size < $count) {
-                       $self->_expand($count);
-                       $size = $self->FETCHSIZE - 1;
-               } else {
-                       while ($size > $count) {
-                               $self->SUPER::pop;
-                               $size = $self->FETCHSIZE - 1;
-                       }
-               }
-       }
-
-       return $size
-}
-
-sub EXISTS {
-       my $self = CORE::shift;
-       my $index = CORE::shift;
-       return $self->FETCHSIZE > abs($index) ? 1 : 0;
-}
-
-sub CLEAR {
-       my $self = CORE::shift;
-       $self->STORESIZE(0);
-       return $self;
-}
-
-sub DELETE {
-       my $self = CORE::shift;
-       my $index = CORE::shift;
-       return $self->removeChild( ($self->childNodes)[$index] );
-}
-
-package OpenSRF::DomainObjectCollection::oilsHash;
-use base qw/OpenSRF::DomainObjectCollection Tie::Hash/;
-
-=head1 NAME
-
-OpenSRF::DomainObjectCollection::oilsHash
-
-=head1 SYNOPSIS
-
-  use OpenSRF::DomainObject::oilsPrimitive;
-
-  my $collection = OpenSRF::DomainObjectCollection::oilsHash->new( key1 => $domain_object, key2 => $another_domain_object, ...);
-
-  $collection->set( key =>'value' );
-  my $value = $collection->find( $key );
-  my $dead_value = $collection->remove( $key );
-  my @keys = $collection->keys;
-  my @values = $collection->values;
-
-    Or, using the TIE interface:
-
-  my %hash;
-  my $real_object = tie(%hash, 'OpenSRF::DomainObjectCollection::oilsHash', domain => $objects, to => $store);
-
-      or to tie an existing $collection object
-
-  my %hash;
-  tie(%hash, 'OpenSRF::DomainObjectCollection::oilsHash', $collection);
-
-      or even....
-
-  my %hash;
-  tie(%hash, ref($collection), $collection);
-
-      or perhaps ...
-
-  my $content = $session->recv->content; # eh? EH?!?!
-  tie(my %hash, ref($content), $content);
-
-  $hash{domain} = $DomainObject; # replaces value for key 'domain' above
-  delete( $hash{to} ); # removes 'to => $store' above.
-  for my $key ( keys %hash ) {
-    ... do stuff ...
-  }
-
-  print $real_object->toString;
-
-=head1 ABSTRACT
-
-This package impliments hash-like domain objects.  A full tie interface
-is also provided.  If elements are passed in as strings (or numbers) they
-are turned into oilsScalar objects.  Any simple scalar or Domain Object may
-be stored in the hash.
-
-=back
-
-=cut
-
-sub tie_me {
-       my $class = shift;
-       $class = ref($class) || $class;
-       my $node = shift;
-       my %hash;
-       tie %hash, $class, $node;
-       return %hash;
-}
-
-
-sub keys {
-       my $self = shift;
-       return map { $_->key } $self->childNodes;
-}
-
-sub values {
-       my $self = shift;
-       return map { $_->value } $self->childNodes;
-}
-
-# an existing DomainObjectCollection::oilsHash can now be tied
-sub TIEHASH {
-       return shift()->new(@_);
-}
-
-sub new {
-       my $class = shift;
-       $class = ref($class) || $class;
-       my $first = shift;
-       
-       return $first
-               if (    defined $first and
-                       ref $first and $first->can('base_type') and
-                       UNIVERSAL::isa($first->class, __PACKAGE__) and
-                       !scalar(@_)
-               );
-       
-       my $self = $class->SUPER::new;
-
-       my @args = @_;
-       if (ref($first) and ref($first) eq 'HASH') {
-               push @args, %$first;
-               tie( %$first, ref($self->upcast), $self);
-       } else {
-               unshift @args, $first if (defined $first);
-       }
-
-       my %arg_hash = @args;
-       while ( my ($key, $value) = each(%arg_hash) ) {
-               $self->STORE($key => $value);
-       }
-       return $self;
-}
-
-sub STORE {
-       shift()->set(@_);
-}
-
-sub set {
-       my $self = shift;
-       my ($key, $value) = @_;
-
-       my $node = $self->find_node($key);
-
-       return $node->value( $value ) if (defined $node);
-       return $self->appendChild( OpenSRF::DomainObject::oilsPair->new($key => $value) );
-}
-
-sub _accessor {
-       my $self = shift;
-       my $key = shift;
-       my $node = find_node($self, $key);
-       return $node->value if ($node);
-}       
-
-sub find_node {
-       my $self = shift;
-       my $key = shift;
-       return ($self->findnodes("oils:domainObject[\@name=\"oilsPair\" and \@key=\"$key\"]", $self))[0];
-}
-
-sub find {
-       my $self = shift;
-       my $key = shift;
-       my $node = $self->find_node($key);
-       my $value = $node->value if (defined $node);
-       return $value;
-}
-
-sub size {
-       my $self = CORE::shift;
-       my @a = $self->childNodes;
-       return scalar(@a);
-}
-
-sub FETCH {
-       my $self = shift;
-       my $key = shift;
-       return $self->find($key);
-}
-
-sub EXISTS {
-       my $self = shift;
-       my $key = shift;
-       return $self->find_node($key);
-}
-
-sub CLEAR {
-       my $self = shift;
-       $self->removeChild for ($self->childNodes);
-       return $self;
-}
-
-sub DELETE {
-       shift()->remove(@_);
-}
-
-sub remove {
-       my $self = shift;
-       my $key = shift;
-       return $self->removeChild( $self->find_node($key) );
-}
-
-sub FIRSTKEY {
-       my $self = shift;
-       return $self->firstChild->key;
-}
-
-sub NEXTKEY {
-       my $self = shift;
-       my $key = shift;
-       my ($prev_node) = $self->find_node($key);
-       my $last_node = $self->lastChild;
-
-       if ($last_node and $last_node->key eq $prev_node->key) {
-               return undef;
-       } else {
-               return $prev_node->nextSibling->key;
-       }
-}
-
-package OpenSRF::DomainObject::oilsHash;
-use base qw/OpenSRF::DomainObjectCollection::oilsHash/;
-
-package OpenSRF::DomainObject::oilsArray;
-use base qw/OpenSRF::DomainObjectCollection::oilsArray/;
-
-1;
index 673516b..bcaf96f 100644 (file)
@@ -1,11 +1,11 @@
 package OpenSRF::DomainObject::oilsResponse;
 use vars qw/@EXPORT_OK %EXPORT_TAGS/;
 use Exporter;
-use JSON;
+use OpenSRF::Utils::JSON;
 use base qw/Exporter/;
 use OpenSRF::Utils::Logger qw/:level/;
 
-JSON->register_class_hint( hint => 'osrfResponse', name => 'OpenSRF::DomainObject::oilsResponse', type => 'hash' );
+OpenSRF::Utils::JSON->register_class_hint( hint => 'osrfResponse', name => 'OpenSRF::DomainObject::oilsResponse', type => 'hash' );
 
 BEGIN {
 @EXPORT_OK = qw/STATUS_CONTINUE STATUS_OK STATUS_ACCEPTED
@@ -74,8 +74,8 @@ my $log = 'OpenSRF::Utils::Logger';
 sub toString {
        my $self = shift;
        my $pretty = shift;
-       return JSON->perl2prettyJSON($self) if ($pretty);
-       return JSON->perl2JSON($self);
+       return OpenSRF::Utils::JSON->perl2prettyJSON($self) if ($pretty);
+       return OpenSRF::Utils::JSON->perl2JSON($self);
 }
 
 sub new {
@@ -106,16 +106,13 @@ sub statusCode {
        return $self->{statusCode};
 }
 
-
 #-------------------------------------------------------------------------------
 
-
-
 package OpenSRF::DomainObject::oilsStatus;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use base 'OpenSRF::DomainObject::oilsResponse';
 use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfStatus', name => 'OpenSRF::DomainObject::oilsStatus', type => 'hash' );
+OpenSRF::Utils::JSON->register_class_hint( hint => 'osrfStatus', name => 'OpenSRF::DomainObject::oilsStatus', type => 'hash' );
 
 =head1 NAME
 
@@ -142,11 +139,13 @@ sets the default B<status> to C<Status> and B<statusCode> to C<STATUS_OK>.
 $status = 'Status';
 $statusCode = STATUS_OK;
 
+#-------------------------------------------------------------------------------
+
 package OpenSRF::DomainObject::oilsConnectStatus;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use base 'OpenSRF::DomainObject::oilsStatus';
 use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfConnectStatus', name => 'OpenSRF::DomainObject::oilsConnectStatus', type => 'hash' );
+OpenSRF::Utils::JSON->register_class_hint( hint => 'osrfConnectStatus', name => 'OpenSRF::DomainObject::oilsConnectStatus', type => 'hash' );
 
 =head1 NAME
 
@@ -177,14 +176,13 @@ B<OpenSRF::DomainObject::oilsStatus>
 $status = 'Connection Successful';
 $statusCode = STATUS_OK;
 
-
-
+#-------------------------------------------------------------------------------
 
 package OpenSRF::DomainObject::oilsContinueStatus;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use base 'OpenSRF::DomainObject::oilsStatus';
 use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfContinueStatus', name => 'OpenSRF::DomainObject::oilsContinueStatus', type => 'hash' );
+OpenSRF::Utils::JSON->register_class_hint( hint => 'osrfContinueStatus', name => 'OpenSRF::DomainObject::oilsContinueStatus', type => 'hash' );
 
 =head1 NAME
 
@@ -216,18 +214,13 @@ $statusCode = STATUS_CONTINUE;
 
 1;
 
-
-
 #-------------------------------------------------------------------------------
 
-
-
 package OpenSRF::DomainObject::oilsResult;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use OpenSRF::DomainObject::oilsPrimitive;
 use base 'OpenSRF::DomainObject::oilsResponse';
 use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfResult', name => 'OpenSRF::DomainObject::oilsResult', type => 'hash' );
+OpenSRF::Utils::JSON->register_class_hint( hint => 'osrfResult', name => 'OpenSRF::DomainObject::oilsResult', type => 'hash' );
 
 
 $status = 'OK';
@@ -284,19 +277,15 @@ B<OpenSRF::DomainObject::oilsResponse>
 
 1;
 
-
-
 #-------------------------------------------------------------------------------
 
-
-
 package OpenSRF::DomainObject::oilsException;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use OpenSRF::EX;
 use base qw/OpenSRF::EX OpenSRF::DomainObject::oilsResponse/;
 use vars qw/$status $statusCode/;
 use Error;
-JSON->register_class_hint( hint => 'osrfException', name => 'OpenSRF::DomainObject::oilsException', type => 'hash' );
+OpenSRF::Utils::JSON->register_class_hint( hint => 'osrfException', name => 'OpenSRF::DomainObject::oilsException', type => 'hash' );
 
 sub message {
        my $self = shift;
@@ -334,12 +323,14 @@ sets the default B<status> to C<Exception occured> and B<statusCode> to C<STATUS
 $status = 'Exception occured';
 $statusCode = STATUS_INTERNALSERVERERROR;
 
+#-------------------------------------------------------------------------------
+
 package OpenSRF::DomainObject::oilsConnectException;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use OpenSRF::EX;
 use base qw/OpenSRF::DomainObject::oilsException OpenSRF::EX::ERROR/;
 use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfConnectException', name => 'OpenSRF::DomainObject::oilsConnectException', type => 'hash' );
+OpenSRF::Utils::JSON->register_class_hint( hint => 'osrfConnectException', name => 'OpenSRF::DomainObject::oilsConnectException', type => 'hash' );
 
 =head1 NAME
 
@@ -371,11 +362,13 @@ B<OpenSRF::DomainObject::oilsException>
 $status = 'Connect Request Failed';
 $statusCode = STATUS_FORBIDDEN;
 
+#-------------------------------------------------------------------------------
+
 package OpenSRF::DomainObject::oilsMethodException;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use base 'OpenSRF::DomainObject::oilsException';
 use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfMethodException', name => 'OpenSRF::DomainObject::oilsMethodException', type => 'hash' );
+OpenSRF::Utils::JSON->register_class_hint( hint => 'osrfMethodException', name => 'OpenSRF::DomainObject::oilsMethodException', type => 'hash' );
 
 =head1 NAME
 
@@ -414,40 +407,40 @@ package OpenSRF::DomainObject::oilsServerError;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use base 'OpenSRF::DomainObject::oilsException';
 use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfServerError', name => 'OpenSRF::DomainObject::oilsServerError', type => 'hash' );
+OpenSRF::Utils::JSON->register_class_hint( hint => 'osrfServerError', name => 'OpenSRF::DomainObject::oilsServerError', type => 'hash' );
 
 $status = 'Internal Server Error';
 $statusCode = STATUS_INTERNALSERVERERROR;
 
 # -------------------------------------------
 
-
-
-
-
 package OpenSRF::DomainObject::oilsBrokenSession;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use OpenSRF::EX;
 use base qw/OpenSRF::DomainObject::oilsException OpenSRF::EX::ERROR/;
 use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfBrokenSession', name => 'OpenSRF::DomainObject::oilsBrokenSession', type => 'hash' );
+OpenSRF::Utils::JSON->register_class_hint( hint => 'osrfBrokenSession', name => 'OpenSRF::DomainObject::oilsBrokenSession', type => 'hash' );
 $status = "Request on Disconnected Session";
 $statusCode = STATUS_EXPFAILED;
 
+#-------------------------------------------------------------------------------
+
 package OpenSRF::DomainObject::oilsXMLParseError;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use OpenSRF::EX;
 use base qw/OpenSRF::DomainObject::oilsException OpenSRF::EX::ERROR/;
 use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfXMLParseError', name => 'OpenSRF::DomainObject::oilsXMLParseError', type => 'hash' );
+OpenSRF::Utils::JSON->register_class_hint( hint => 'osrfXMLParseError', name => 'OpenSRF::DomainObject::oilsXMLParseError', type => 'hash' );
 $status = "XML Parse Error";
 $statusCode = STATUS_EXPFAILED;
 
+#-------------------------------------------------------------------------------
+
 package OpenSRF::DomainObject::oilsAuthException;
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use OpenSRF::EX;
 use base qw/OpenSRF::DomainObject::oilsException OpenSRF::EX::ERROR/;
-JSON->register_class_hint( hint => 'osrfAuthException', name => 'OpenSRF::DomainObject::oilsAuthException', type => 'hash' );
+OpenSRF::Utils::JSON->register_class_hint( hint => 'osrfAuthException', name => 'OpenSRF::DomainObject::oilsAuthException', type => 'hash' );
 use vars qw/$status $statusCode/;
 $status = "Authentication Failure";
 $statusCode = STATUS_FORBIDDEN;
diff --git a/src/perlmods/OpenSRF/DomainObject/oilsSearch.pm b/src/perlmods/OpenSRF/DomainObject/oilsSearch.pm
deleted file mode 100644 (file)
index b2e23e4..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-package OpenSRF::DomainObject::oilsSearch;
-use OpenSRF::DomainObject;
-use OpenSRF::DomainObject::oilsPrimitive;
-use OpenSRF::DOM::Element::searchCriteria;
-use base 'OpenSRF::DomainObject';
-
-sub new {
-       my $class = shift;
-       $class = ref($class) || $class;
-
-       unshift @_, 'table' if (@_ == 1);
-       my %args = @_;
-
-       my $self = $class->SUPER::new;
-       
-       for my $part ( keys %args ) {
-               if ($part ne 'criteria') {
-                       $self->$part( $args{$part} );
-                       next;
-               }
-               $self->criteria( OpenSRF::DOM::Element::searchCriteria->new( @{$args{$part}} ) );
-       }
-       return $self;
-}
-
-sub format {
-       my $self = shift;
-       return $self->_attr_get_set( format => shift );
-}
-
-sub table {
-       my $self = shift;
-       return $self->_attr_get_set( table => shift );
-}
-
-sub fields {
-       my $self = shift;
-       my $new_fields_ref = shift;
-
-       my ($old_fields) = $self->getChildrenByTagName("oils:domainObjectCollection");
-       
-       if ($new_fields_ref) {
-               my $do = OpenSRF::DomainObjectCollection::oilsArray->new( @$new_fields_ref );
-               if (defined $old_fields) {
-                       $old_fields->replaceNode($do);
-               } else {
-                       $self->appendChild($do);
-                       return $do->list;
-               }
-       }
-
-       return $old_fields->list if ($old_fields);
-}
-
-sub limit {
-       my $self = shift;
-       return $self->_attr_get_set( limit => shift );
-}
-
-sub offset {
-       my $self = shift;
-       return $self->_attr_get_set( offset => shift );
-}
-
-sub group_by {
-       my $self = shift;
-       return $self->_attr_get_set( group_by => shift );
-}
-
-sub criteria {
-       my $self = shift;
-       my $new_crit = shift;
-
-       if (@_) {
-               unshift @_, $new_crit;
-               $new_crit = OpenSRF::DOM::Element::searchCriteria->new(@_);
-       }
-
-       my ($old_crit) = $self->getChildrenByTagName("oils:searchCriteria");
-       
-       if (defined $new_crit) {
-               if (defined $old_crit) {
-                       $old_crit->replaceNode($new_crit);
-               } else {
-                       $self->appendChild($new_crit);
-                       return $new_crit;
-               }
-       }
-
-       return $old_crit;
-}
-
-sub toSQL {
-       my $self = shift;
-
-       my $SQL  = 'SELECT    ' . join(',', $self->fields);
-          $SQL .= '  FROM    ' . $self->table;
-          $SQL .= '  WHERE   ' . $self->criteria->toSQL if ($self->criteria);
-          $SQL .= ' GROUP BY ' . $self->group_by if ($self->group_by);
-          $SQL .= '  LIMIT   ' . $self->limit if ($self->limit);
-          $SQL .= '  OFFSET  ' . $self->offset if ($self->offset);
-       
-       return $SQL;
-}
-
-1;
diff --git a/src/perlmods/OpenSRF/DomainObjectCollection.pm b/src/perlmods/OpenSRF/DomainObjectCollection.pm
deleted file mode 100644 (file)
index 7049af7..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-package OpenSRF::DomainObjectCollection;
-use base 'OpenSRF::DOM::Element::domainObjectCollection';
-use OpenSRF::DOM;
-use OpenSRF::Utils::Logger qw(:level);
-my $logger = "OpenSRF::Utils::Logger";
-
-=head1 NAME
-
-OpenSRF::DomainObjectCollection
-
-=head1 SYNOPSIS
-
-OpenSRF::DomainObjectCollection is an abstract base class.  It
-should not be used directly.  See C<OpenSRF::DomainObjectCollection::*>
-for details.
-
-=cut
-
-sub new {
-       my $class = shift;
-       $class = ref($class) || $class;
-
-       my @args = shift;
-
-       (my $type = $class) =~ s/^.+://o;
-
-       my $doc = OpenSRF::DOM->createDocument;
-       my $dO = OpenSRF::DOM::Element::domainObjectCollection->new( $type, @args );
-
-       $doc->documentElement->appendChild($dO);
-
-       return $dO;
-}
-
-1;
index 7b2cfb0..8aff411 100644 (file)
@@ -179,34 +179,6 @@ Thrown where an argument to a method was invalid or not provided
 
 
 # -------------------------------------------------------------------
-package OpenSRF::EX::NotADomainObject;
-use base 'OpenSRF::EX::ERROR';
-our $ex_msg_header = "Must be a Domain Object";
-
-=head2 OpenSRF::EX::NotADomainObject
-
-Thrown where a OpenSRF::DomainObject::oilsScalar or
-OpenSRF::DomainObject::oilsPair was passed a value that
-is not a perl scalar or a OpenSRF::DomainObject.
-
-=cut
-
-
-# -------------------------------------------------------------------
-package OpenSRF::EX::ArrayOutOfBounds;
-use base 'OpenSRF::EX::ERROR';
-our $ex_msg_header = "Tied array access on a nonexistant index";
-
-=head2 OpenSRF::EX::ArrayOutOfBounds
-
-Thrown where a TIEd array (OpenSRF::DomainObject::oilsArray) was accessed at
-a nonexistant index
-
-=cut
-
-
-
-# -------------------------------------------------------------------
 package OpenSRF::EX::Socket;
 use base 'OpenSRF::EX::ERROR';
 our $ex_msg_header = "Socket Exception";
index cf3e840..ba86243 100644 (file)
@@ -8,9 +8,8 @@ use OpenSRF::Transport;
 use OpenSRF::UnixServer;
 use OpenSRF::Utils;
 use OpenSRF::Utils::LogServer;
-use OpenSRF::DOM;
 use OpenSRF::EX qw/:try/;
-use POSIX ":sys_wait_h";
+use POSIX qw/setsid :sys_wait_h/;
 use OpenSRF::Utils::Config; 
 use OpenSRF::Utils::SettingsParser;
 use OpenSRF::Utils::SettingsClient;
@@ -111,7 +110,7 @@ sub load_bootstrap_config {
 
        OpenSRF::Utils::Config->load( config_file => $bootstrap_config_file );
 
-       JSON->register_class_hint( name => "OpenSRF::Application", hint => "method", type => "hash" );
+       OpenSRF::Utils::JSON->register_class_hint( name => "OpenSRF::Application", hint => "method", type => "hash" );
 
        OpenSRF::Transport->message_envelope(  "OpenSRF::Transport::SlimJabber::MessageWrapper" );
        OpenSRF::Transport::PeerHandle->set_peer_client(  "OpenSRF::Transport::SlimJabber::PeerConnection" );
@@ -127,7 +126,13 @@ sub bootstrap {
        my $bsconfig = OpenSRF::Utils::Config->current;
 
        # Start a process group and make me the captain
-       setpgrp( 0, 0 ); 
+       exit if (OpenSRF::Utils::safe_fork());
+       chdir('/');
+       setsid(); 
+       close STDIN;
+       close STDOUT;
+       close STDERR;
+
        $0 = "OpenSRF System";
 
        # -----------------------------------------------
index 4ee322c..9af9282 100644 (file)
@@ -3,6 +3,7 @@ use strict; use warnings;
 use base 'OpenSRF';
 use Time::HiRes qw/time/;
 use OpenSRF::AppSession;
+use OpenSRF::Utils::JSON;
 use OpenSRF::Utils::Logger qw(:level);
 use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use OpenSRF::EX qw/:try/;
@@ -118,7 +119,7 @@ sub handler {
 
        # Create a document from the JSON contained within the message 
        my $doc; 
-       eval { $doc = JSON->JSON2perl($body); };
+       eval { $doc = OpenSRF::Utils::JSON->JSON2perl($body); };
        if( $@ ) {
 
                $logger->transport( "Received bogus JSON: $@", INFO );
index 120f73c..472bb44 100644 (file)
@@ -10,7 +10,7 @@ use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use OpenSRF::System;
 use OpenSRF::Utils::SettingsClient;
 use Time::HiRes qw(time);
-use JSON;
+use OpenSRF::Utils::JSON;
 use vars qw/@ISA $app/;
 use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
 use Carp;
@@ -208,7 +208,7 @@ sub configure_hook {
        my $imp = $client->config_value("apps", $app, "implementation");
        OpenSRF::Application::server_class($app);
        OpenSRF::Application->application_implementation( $imp );
-       JSON->register_class_hint( name => $imp, hint => $app, type => "hash" );
+       OpenSRF::Utils::JSON->register_class_hint( name => $imp, hint => $app, type => "hash" );
        OpenSRF::Application->application_implementation->initialize()
                if (OpenSRF::Application->application_implementation->can('initialize'));
 
index ac430bd..635a2b3 100644 (file)
@@ -6,7 +6,7 @@ use OpenSRF::Utils::Logger qw/:level/;
 use OpenSRF::Utils::Config;
 use OpenSRF::Utils::SettingsClient;
 use OpenSRF::EX qw(:try);
-use JSON;
+use OpenSRF::Utils::JSON;
 
 my $log = 'OpenSRF::Utils::Logger';
 
@@ -96,7 +96,7 @@ sub put_cache {
        my($self, $key, $value, $expiretime ) = @_;
        return undef unless( defined $key and defined $value );
 
-       $value = JSON->perl2JSON($value);
+       $value = OpenSRF::Utils::JSON->perl2JSON($value);
 
        if($self->{persist}){ _load_methods(); }
 
@@ -148,7 +148,7 @@ sub get_cache {
        my($self, $key ) = @_;
 
        my $val = $self->{memcache}->get( $key );
-       return JSON->JSON2perl($val) if defined($val);
+       return OpenSRF::Utils::JSON->JSON2perl($val) if defined($val);
 
        if($self->{persist}){ _load_methods(); }
 
@@ -162,7 +162,7 @@ sub get_cache {
                        } else {
                                $self->{memcache}->set( $key, $val, $max_persist_time);
                        }
-                       return JSON->JSON2perl($val);
+                       return OpenSRF::Utils::JSON->JSON2perl($val);
                } 
        }
        return undef;
diff --git a/src/perlmods/OpenSRF/Utils/JSON.pm b/src/perlmods/OpenSRF/Utils/JSON.pm
new file mode 100644 (file)
index 0000000..b417425
--- /dev/null
@@ -0,0 +1,827 @@
+
+package OpenSRF::Utils::JSON::number;
+sub new {
+       my $class = shift;
+       my $x = shift || $class;
+       return bless \$x => __PACKAGE__;
+}
+
+use overload ( '""' => \&toString );
+
+sub toString { defined($_[1]) ? ${$_[1]} : ${$_[0]} }
+
+package OpenSRF::Utils::JSON::bool::true;
+sub new { return bless {} => __PACKAGE__ }
+use overload ( '""' => \&toString );
+use overload ( 'bool' => sub { 1 } );
+use overload ( '0+' => sub { 1 } );
+
+sub toString { 'true' }
+
+package OpenSRF::Utils::JSON::bool::false;
+sub new { return bless {} => __PACKAGE__ }
+use overload ( '""' => \&toString );
+use overload ( 'bool' => sub { 0 } );
+use overload ( '0+' => sub { 0 } );
+
+sub toString { 'false' }
+
+package OpenSRF::Utils::JSON;
+use Unicode::Normalize;
+use vars qw/%_class_map/;
+
+sub register_class_hint {
+       my $class = shift;
+       my %args = @_;
+
+       $_class_map{hints}{$args{hint}} = \%args;
+       $_class_map{classes}{$args{name}} = \%args;
+}
+
+sub _JSON_regex {
+       my $string = shift;
+
+       $string =~ s/^\s* ( 
+                          {                            | # start object
+                          \[                           | # start array
+                          -?\d+\.?\d*                  | # number literal
+                          "(?:(?:\\[\"])|[^\"])*"      | # string literal
+                          (?:\/\*.+?\*\/)              | # C comment
+                          true                         | # bool true
+                          false                        | # bool false
+                          null                         | # undef()
+                          :                            | # object key-value sep
+                          ,                            | # list sep
+                          \]                           | # array end
+                          }                              # object end
+                       )
+                \s*//sox;
+       return ($string,$1);
+}
+
+sub lookup_class {
+       my $self = shift;
+       my $hint = shift;
+       return $_class_map{hints}{$hint}{name}
+}
+
+sub lookup_hint {
+       my $self = shift;
+       my $class = shift;
+       return $_class_map{classes}{$class}{hint}
+}
+
+sub _json_hint_to_class {
+       my $type = shift;
+       my $hint = shift;
+
+       return $_class_map{hints}{$hint}{name} if (exists $_class_map{hints}{$hint});
+       
+       $type = 'hash' if ($type eq '}');
+       $type = 'array' if ($type eq ']');
+
+       OpenSRF::Utils::JSON->register_class_hint(name => $hint, hint => $hint, type => $type);
+
+       return $hint;
+}
+
+sub JSON2perl {
+       my $class = shift;
+       local $_ = shift;
+
+       s/(?<!\\)\$/\\\$/gmo; # fixup $ for later
+       s/(?<!\\)\@/\\\@/gmo; # fixup @ for later
+       s/(?<!\\)\%/\\\%/gmo; # fixup % for later
+
+       # Convert JSON Unicode...
+       s/\\u([0-9a-fA-F]{4})/chr(hex($1))/esog;
+
+       # handle class blessings
+       s/\/\*--\s*S\w*?\s+\S+\s*--\*\// bless(/sog;
+       s/(\]|\}|")\s*\/\*--\s*E\w*?\s+(\S+)\s*--\*\//$1 => _json_hint_to_class("$1", "$2")) /sog;
+
+       my $re = qr/((?<!\\)"(?>(?<=\\)"|[^"])*(?<!\\)")/;
+       # Grab strings...
+       my @strings = /$re/sog;
+
+       # Replace with code...
+       #s/"(?:(?:\\[\"])|[^\"])*"/ do{ \$t = '"'.shift(\@strings).'"'; eval \$t;} /sog;
+       s/$re/ eval shift(\@strings) /sog;
+
+       # Perlify hash notation
+       s/:/ => /sog;
+
+       # Do numbers...
+       #s/\b(-?\d+\.?\d*)\b/ OpenSRF::Utils::JSON::number::new($1) /sog;
+
+       # Change javascript stuff to perl...
+       s/null/ undef /sog;
+       s/true/ bless( {}, "OpenSRF::Utils::JSON::bool::true") /sog;
+       s/false/ bless( {}, "OpenSRF::Utils::JSON::bool::false") /sog;
+
+       my $ret;
+       return eval '$ret = '.$_;
+}
+
+my $_json_index;
+sub ___JSON2perl {
+       my $class = shift;
+       my $data = shift;
+
+       $data = [ split //, $data ];
+
+       $_json_index = 0;
+
+       return _json_parse_data($data);
+}
+
+sub _eat_WS {
+       my $data = shift;
+       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+}
+
+sub _json_parse_data {
+       my $data = shift;
+
+       my $out; 
+
+       #warn "parse_data";
+
+       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+
+       my $class = '';
+
+       my $c = $$data[$_json_index];
+
+       if ($c eq '/') {
+               $_json_index++;
+               $class = _json_parse_comment($data);
+               
+               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+               $c = $$data[$_json_index];
+       }
+
+       if ($c eq '"') {
+               $_json_index++;
+               my $val = '';
+
+               my $seen_slash = 0;
+               my $done = 0;
+               while (!$done) {
+                       my $c = $$data[$_json_index];
+                       #warn "c is $c";
+
+                       if ($c eq '\\') {
+                               if ($seen_slash) {
+                                       $val .= '\\';
+                                       $seen_slash = 0;
+                               } else {
+                                       $seen_slash = 1;
+                               }
+                       } elsif ($c eq '"') {
+                               if ($seen_slash) {
+                                       $val .= '"';
+                                       $seen_slash = 0;
+                               } else {
+                                       $done = 1;
+                               }
+                       } elsif ($c eq 't') {
+                               if ($seen_slash) {
+                                       $val .= "\t";
+                                       $seen_slash = 0;
+                               } else {
+                                       $val .= 't';
+                               }
+                       } elsif ($c eq 'b') {
+                               if ($seen_slash) {
+                                       $val .= "\b";
+                                       $seen_slash = 0;
+                               } else {
+                                       $val .= 'b';
+                               }
+                       } elsif ($c eq 'f') {
+                               if ($seen_slash) {
+                                       $val .= "\f";
+                                       $seen_slash = 0;
+                               } else {
+                                       $val .= 'f';
+                               }
+                       } elsif ($c eq 'r') {
+                               if ($seen_slash) {
+                                       $val .= "\r";
+                                       $seen_slash = 0;
+                               } else {
+                                       $val .= 'r';
+                               }
+                       } elsif ($c eq 'n') {
+                               if ($seen_slash) {
+                                       $val .= "\n";
+                                       $seen_slash = 0;
+                               } else {
+                                       $val .= 'n';
+                               }
+                       } elsif ($c eq 'u') {
+                               if ($seen_slash) {
+                                       $_json_index++;
+                                       $val .= chr(hex(join('',$$data[$_json_index .. $_json_index + 3])));
+                                       $_json_index += 3;
+                                       $seen_slash = 0;
+                               } else {
+                                       $val .= 'u';
+                               }
+                       } else {
+                               $val .= $c;
+                       }
+                       $_json_index++;
+
+                       #warn "string is $val";
+               }
+
+               $out = $val;
+
+               #$out = _json_parse_string($data);
+       } elsif ($c eq '[') {
+               $_json_index++;
+               $out = [];
+
+               my $in_parse = 0;
+               my $done = 0;
+               while(!$done) {
+                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+
+                       if ($$data[$_json_index] eq ']') {
+                               $done = 1;
+                               $_json_index++;
+                               last;
+                       }
+
+                       if ($in_parse) {
+                               if ($$data[$_json_index] ne ',') {
+                                       #warn "_json_parse_array: bad data, leaving array parser";
+                                       last;
+                               }
+                               $_json_index++;
+                               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+                       }
+
+                       my $item = _json_parse_data($data);
+
+                       push @$out, $item;
+                       $in_parse++;
+               }
+
+               #$out = _json_parse_array($data);
+       } elsif ($c eq '{') {
+               $_json_index++;
+               $out = {};
+
+               my $in_parse = 0;
+               my $done = 0;
+               while(!$done) {
+                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+
+                       if ($$data[$_json_index] eq '}') {
+                               $done = 1;
+                               $_json_index++;
+                               last;
+                       }
+
+                       if ($in_parse) {
+                               if ($$data[$_json_index] ne ',') {
+                                       #warn "_json_parse_object: bad data, leaving object parser";
+                                       last;
+                               }
+                               $_json_index++;
+                               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+                       }
+
+                       my ($key,$value);
+                       $key = _json_parse_data($data);
+
+                       #warn "object key is $key";
+
+                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+               
+                       if ($$data[$_json_index] ne ':') {
+                               #warn "_json_parse_object: bad data, leaving object parser";
+                               last;
+                       }
+                       $_json_index++;
+                       $value = _json_parse_data($data);
+
+                       $out->{$key} = $value;
+                       $in_parse++;
+               }
+               #$out = _json_parse_object($data);
+       } elsif (lc($c) eq 'n') {
+               if (lc(join('',$$data[$_json_index .. $_json_index + 3])) eq 'null') {
+                       $_json_index += 4;
+               } else {
+                       warn "CRAP! bad null parsing...";
+               }
+               $out = undef;
+               #$out = _json_parse_null($data);
+       } elsif (lc($c) eq 't' or lc($c) eq 'f') {
+               if (lc(join('',$$data[$_json_index .. $_json_index + 3])) eq 'true') {
+                       $out = 1;
+                       $_json_index += 4;
+               } elsif (lc(join('',$$data[$_json_index .. $_json_index + 4])) eq 'false') {
+                       $out = 0;
+                       $_json_index += 5;
+               } else {
+                       #warn "CRAP! bad bool parsing...";
+                       $out = undef;
+               }
+               #$out = _json_parse_bool($data);
+       } elsif ($c =~ /\d+/o or $c eq '.' or $c eq '-') {
+               my $val;
+               while ($$data[$_json_index] =~ /[-\.0-9]+/io) {
+                       $val .= $$data[$_json_index];
+                       $_json_index++;
+               }
+               $out = 0+$val;
+               #$out = _json_parse_number($data);
+       }
+
+       if ($class) {
+               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+               my $c = $$data[$_json_index];
+
+               if ($c eq '/') {
+                       $_json_index++;
+                       _json_parse_comment($data)
+               }
+
+               bless( $out => lookup_class($class) );
+       }
+
+       $out;
+}
+
+sub _json_parse_null {
+       my $data = shift;
+
+       #warn "parse_null";
+
+       if (lc(join('',$$data[$_json_index .. $_json_index + 3])) eq 'null') {
+               $_json_index += 4;
+       } else {
+               #warn "CRAP! bad null parsing...";
+       }
+       return undef;
+}
+
+sub _json_parse_bool {
+       my $data = shift;
+
+       my $out;
+
+       #warn "parse_bool";
+
+       if (lc(join('',$$data[$_json_index .. $_json_index + 3])) eq 'true') {
+               $out = 1;
+               $_json_index += 4;
+       } elsif (lc(join('',$$data[$_json_index .. $_json_index + 4])) eq 'false') {
+               $out = 0;
+               $_json_index += 5;
+       } else {
+               #warn "CRAP! bad bool parsing...";
+               $out = undef;
+       }
+       return $out;
+}
+
+sub _json_parse_number {
+       my $data = shift;
+
+       #warn "parse_number";
+
+       my $val;
+       while ($$data[$_json_index] =~ /[-\.0-9]+/io) {
+               $val .= $$data[$_json_index];
+               $_json_index++;
+       }
+
+       return 0+$val;
+}
+
+sub _json_parse_object {
+       my $data = shift;
+
+       #warn "parse_object";
+
+       my $out = {};
+
+       my $in_parse = 0;
+       my $done = 0;
+       while(!$done) {
+               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+
+               if ($$data[$_json_index] eq '}') {
+                       $done = 1;
+                       $_json_index++;
+                       last;
+               }
+
+               if ($in_parse) {
+                       if ($$data[$_json_index] ne ',') {
+                               #warn "_json_parse_object: bad data, leaving object parser";
+                               last;
+                       }
+                       $_json_index++;
+                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+               }
+
+               my ($key,$value);
+               $key = _json_parse_data($data);
+
+               #warn "object key is $key";
+
+               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+               
+               if ($$data[$_json_index] ne ':') {
+                       #warn "_json_parse_object: bad data, leaving object parser";
+                       last;
+               }
+               $_json_index++;
+               $value = _json_parse_data($data);
+
+               $out->{$key} = $value;
+               $in_parse++;
+       }
+
+       return $out;
+}
+
+sub _json_parse_array {
+       my $data = shift;
+
+       #warn "parse_array";
+
+       my $out = [];
+
+       my $in_parse = 0;
+       my $done = 0;
+       while(!$done) {
+               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+
+               if ($$data[$_json_index] eq ']') {
+                       $done = 1;
+                       $_json_index++;
+                       last;
+               }
+
+               if ($in_parse) {
+                       if ($$data[$_json_index] ne ',') {
+                               #warn "_json_parse_array: bad data, leaving array parser";
+                               last;
+                       }
+                       $_json_index++;
+                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+               }
+
+               my $item = _json_parse_data($data);
+
+               push @$out, $item;
+               $in_parse++;
+       }
+
+       return $out;
+}
+
+
+sub _json_parse_string {
+       my $data = shift;
+
+       #warn "parse_string";
+
+       my $val = '';
+
+       my $seen_slash = 0;
+       my $done = 0;
+       while (!$done) {
+               my $c = $$data[$_json_index];
+               #warn "c is $c";
+
+               if ($c eq '\\') {
+                       if ($seen_slash) {
+                               $val .= '\\';
+                               $seen_slash = 0;
+                       } else {
+                               $seen_slash = 1;
+                       }
+               } elsif ($c eq '"') {
+                       if ($seen_slash) {
+                               $val .= '"';
+                               $seen_slash = 0;
+                       } else {
+                               $done = 1;
+                       }
+               } elsif ($c eq 't') {
+                       if ($seen_slash) {
+                               $val .= "\t";
+                               $seen_slash = 0;
+                       } else {
+                               $val .= 't';
+                       }
+               } elsif ($c eq 'b') {
+                       if ($seen_slash) {
+                               $val .= "\b";
+                               $seen_slash = 0;
+                       } else {
+                               $val .= 'b';
+                       }
+               } elsif ($c eq 'f') {
+                       if ($seen_slash) {
+                               $val .= "\f";
+                               $seen_slash = 0;
+                       } else {
+                               $val .= 'f';
+                       }
+               } elsif ($c eq 'r') {
+                       if ($seen_slash) {
+                               $val .= "\r";
+                               $seen_slash = 0;
+                       } else {
+                               $val .= 'r';
+                       }
+               } elsif ($c eq 'n') {
+                       if ($seen_slash) {
+                               $val .= "\n";
+                               $seen_slash = 0;
+                       } else {
+                               $val .= 'n';
+                       }
+               } elsif ($c eq 'u') {
+                       if ($seen_slash) {
+                               $_json_index++;
+                               $val .= chr(hex(join('',$$data[$_json_index .. $_json_index + 3])));
+                               $_json_index += 3;
+                               $seen_slash = 0;
+                       } else {
+                               $val .= 'u';
+                       }
+               } else {
+                       $val .= $c;
+               }
+               $_json_index++;
+
+               #warn "string is $val";
+       }
+
+       return $val;
+}
+
+sub _json_parse_comment {
+       my $data = shift;
+
+       #warn "parse_comment";
+
+       if ($$data[$_json_index] eq '/') {
+               $_json_index++;
+               while (!($$data[$_json_index] eq "\n")) { $_json_index++ }
+               $_json_index++;
+               return undef;
+       }
+
+       my $class = '';
+
+       if (join('',$$data[$_json_index .. $_json_index + 2]) eq '*--') {
+               $_json_index += 3;
+               while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+               if ($$data[$_json_index] eq 'S') {
+                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+                       while ($$data[$_json_index] !~ /[-\s]+/o) {
+                               $class .= $$data[$_json_index];
+                               $_json_index++;
+                       }
+                       while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
+               }
+       }
+
+       while ($$data[$_json_index] ne '/') { $_json_index++ };
+       $_json_index++;
+
+       return $class;
+}
+
+sub old_JSON2perl {
+       my ($class, $json) = @_;
+
+       if (!defined($json)) {
+               return undef;
+       }
+
+       $json =~ s/(?<!\\)\$/\\\$/gmo; # fixup $ for later
+       $json =~ s/(?<!\\)\@/\\\@/gmo; # fixup @ for later
+       $json =~ s/(?<!\\)\%/\\\%/gmo; # fixup % for later
+
+       my @casts;
+       my $casting_depth = 0;
+       my $current_cast;
+       my $element;
+       my $output = '';
+       while (($json,$element) = _JSON_regex($json)) {
+
+               last unless ($element);
+
+               if ($element eq 'null') {
+                       $output .= ' undef() ';
+                       next;
+               } elsif ($element =~ /^\/\*--\s*S\w*?\s+(\w+)\s*--\*\/$/) {
+                       my $hint = $1;
+                       if (exists $_class_map{hints}{$hint}) {
+                               $casts[$casting_depth] = $hint;
+                               $output .= ' bless(';
+                       }
+                       next;
+               } elsif ($element =~ /^\/\*/) {
+                       next;
+               } elsif ($element =~ /^\d/) {
+                       $output .= "do { OpenSRF::Utils::JSON::number::new($element) }";
+                       next;
+               } elsif ($element eq '{' or $element eq '[') {
+                       $casting_depth++;
+               } elsif ($element eq '}' or $element eq ']') {
+                       $casting_depth--;
+                       my $hint = $casts[$casting_depth];
+                       $casts[$casting_depth] = undef;
+                       if (defined $hint and exists $_class_map{hints}{$hint}) {
+                               $output .= $element . ',"'. $_class_map{hints}{$hint}{name} . '")';
+                               next;
+                       }
+               } elsif ($element eq ':') {
+                       $output .= ' => ';
+                       next;
+               } elsif ($element eq 'true') {
+                       $output .= 'bless( {}, "OpenSRF::Utils::JSON::bool::true")';
+                       next;
+               } elsif ($element eq 'false') {
+                       $output .= 'bless( {}, "OpenSRF::Utils::JSON::bool::false")';
+                       next;
+               }
+               
+               $output .= $element;
+       }
+
+       return eval $output;
+}
+
+sub perl2JSON {
+       my ($class, $perl, $strict) = @_;
+
+       my $output = '';
+       if (!defined($perl)) {
+               $output = '' if $strict;
+               $output = 'null' unless $strict;
+       } elsif (ref($perl) and ref($perl) =~ /^OpenSRF::Utils::JSON/) {
+               $output .= $perl;
+       } elsif ( ref($perl) && exists($_class_map{classes}{ref($perl)}) ) {
+               $output .= '/*--S '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
+               if (lc($_class_map{classes}{ref($perl)}{type}) eq 'hash') {
+                       my %hash =  %$perl;
+                       $output .= perl2JSON(undef,\%hash, $strict);
+               } elsif (lc($_class_map{classes}{ref($perl)}{type}) eq 'array') {
+                       my @array =  @$perl;
+                       $output .= perl2JSON(undef,\@array, $strict);
+               }
+               $output .= '/*--E '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
+       } elsif (ref($perl) and ref($perl) =~ /HASH/) {
+               $output .= '{';
+               my $c = 0;
+               for my $key (sort keys %$perl) {
+                       my $outkey = NFC($key);
+                       $output .= ',' if ($c); 
+
+                       $outkey =~ s{\\}{\\\\}sgo;
+                       $outkey =~ s/"/\\"/sgo;
+                       $outkey =~ s/\t/\\t/sgo;
+                       $outkey =~ s/\f/\\f/sgo;
+                       $outkey =~ s/\r/\\r/sgo;
+                       $outkey =~ s/\n/\\n/sgo;
+                       $outkey =~ s/([\x{0080}-\x{fffd}])/sprintf('\u%0.4x',ord($1))/sgoe;
+
+                       $output .= '"'.$outkey.'":'. perl2JSON(undef,$$perl{$key}, $strict);
+                       $c++;
+               }
+               $output .= '}';
+       } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
+               $output .= '[';
+               my $c = 0;
+               for my $part (@$perl) {
+                       $output .= ',' if ($c); 
+                       
+                       $output .= perl2JSON(undef,$part, $strict);
+                       $c++;
+               }
+               $output .= ']';
+       } elsif (ref($perl) and ref($perl) =~ /CODE/) {
+               $output .= perl2JSON(undef,$perl->(), $strict);
+       } elsif (ref($perl) and ("$perl" =~ /^([^=]+)=(\w+)/o)) {
+               my $type = $2;
+               my $name = $1;
+               OpenSRF::Utils::JSON->register_class_hint(name => $name, hint => $name, type => lc($type));
+               $output .= perl2JSON(undef,$perl, $strict);
+       } else {
+               $perl = NFC($perl);
+               $perl =~ s{\\}{\\\\}sgo;
+               $perl =~ s/"/\\"/sgo;
+               $perl =~ s/\t/\\t/sgo;
+               $perl =~ s/\f/\\f/sgo;
+               $perl =~ s/\r/\\r/sgo;
+               $perl =~ s/\n/\\n/sgo;
+               $perl =~ s/([\x{0080}-\x{fffd}])/sprintf('\u%0.4x',ord($1))/sgoe;
+               if (length($perl) < 10 and $perl =~ /^(?:\+|-)?\d*\.?\d+$/o and $perl !~ /^(?:\+|-)?0\d+/o ) {
+                       $output = $perl;
+               } else {
+                       $output = '"'.$perl.'"';
+               }
+       }
+
+       return $output;
+}
+
+my $depth = 0;
+sub perl2prettyJSON {
+       my ($class, $perl, $nospace) = @_;
+       $perl ||= $class;
+
+       my $output = '';
+       if (!defined($perl)) {
+               $output = "   "x$depth unless($nospace);
+               $output .= 'null';
+       } elsif (ref($perl) and ref($perl) =~ /^OpenSRF::Utils::JSON/) {
+               $output = "   "x$depth unless($nospace);
+               $output .= $perl;
+       } elsif ( ref($perl) && exists($_class_map{classes}{ref($perl)}) ) {
+               $depth++;
+               $output .= "\n";
+               $output .= "   "x$depth;
+               $output .= '/*--S '.$_class_map{classes}{ref($perl)}{hint}."--*/ ";
+               if (lc($_class_map{classes}{ref($perl)}{type}) eq 'hash') {
+                       my %hash =  %$perl;
+                       $output .= perl2prettyJSON(\%hash,undef,1);
+               } elsif (lc($_class_map{classes}{ref($perl)}{type}) eq 'array') {
+                       my @array =  @$perl;
+                       $output .= perl2prettyJSON(\@array,undef,1);
+               }
+               $output .= ' /*--E '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
+               $depth--;
+       } elsif (ref($perl) and ref($perl) =~ /HASH/) {
+               $output .= "   "x$depth unless ($nospace);
+               $output .= "{\n";
+               my $c = 0;
+               $depth++;
+               for my $key (sort keys %$perl) {
+                       $output .= ",\n" if ($c); 
+                       $output .= "   "x$depth;
+                       $output .= perl2prettyJSON($key)." : ".perl2prettyJSON($$perl{$key}, undef, 1);
+                       $c++;
+               }
+               $depth--;
+               $output .= "\n";
+               $output .= "   "x$depth;
+               $output .= '}';
+       } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
+               $output .= "   "x$depth unless ($nospace);
+               $output .= "[\n";
+               my $c = 0;
+               $depth++;
+               for my $part (@$perl) {
+                       $output .= ",\n" if ($c); 
+                       $output .= "   "x$depth;
+                       $output .= perl2prettyJSON($part);
+                       $c++;
+               }
+               $depth--;
+               $output .= "\n";
+               $output .= "   "x$depth;
+               $output .= "]";
+       } elsif (ref($perl) and ref($perl) =~ /CODE/) {
+               $output .= perl2prettyJSON(undef,$perl->(), $nospace);
+       } elsif (ref($perl) and "$perl" =~ /^([^=]+)=(\w{4,5})\(0x/) {
+               my $type = $2;
+               my $name = $1;
+               register_class_hint(undef, name => $name, hint => $name, type => lc($type));
+               $output .= perl2prettyJSON(undef,$perl);
+       } else {
+               $perl = NFC($perl);
+               $perl =~ s/\\/\\\\/sgo;
+               $perl =~ s/"/\\"/sgo;
+               $perl =~ s/\t/\\t/sgo;
+               $perl =~ s/\f/\\f/sgo;
+               $perl =~ s/\r/\\r/sgo;
+               $perl =~ s/\n/\\n/sgo;
+               $perl =~ s/([\x{0080}-\x{fffd}])/sprintf('\u%0.4x',ord($1))/sgoe;
+               $output .= "   "x$depth unless($nospace);
+               if (length($perl) < 10 and $perl =~ /^(?:\+|-)?\d*\.?\d+$/o and $perl !~ /^(?:\+|-)?0\d+/o ) {
+                       $output = $perl;
+               } else {
+                       $output = '"'.$perl.'"';
+               }
+       }
+
+       return $output;
+}
+
+1;
index 138aa01..8734115 100644 (file)
@@ -66,18 +66,12 @@ sub set_config {
        }
 
        $loglevel =  $config->bootstrap->loglevel; 
-       if($loglevel = 1){ $loglevel = ERROR(); }
-       elsif($loglevel = 2){ $loglevel = WARN(); }
-       elsif($loglevel = 3){ $loglevel = INFO(); }
-       elsif($loglevel = 4){ $loglevel = DEBUG(); }
-       elsif($loglevel = 5){ $loglevel = INTERNAL(); }
-       else{$loglevel= INFO(); }
 
        $logfile = $config->bootstrap->logfile;
        if($logfile =~ /^syslog/) {
                $syslog_enabled = 1;
                $logfile_enabled = 0;
-               $logfile =~ s/^syslog:?//;
+        $logfile = $config->bootstrap->syslog;
                $facility = $logfile;
                $logfile = undef;
                $facility = _fac_to_const($facility);
@@ -85,16 +79,28 @@ sub set_config {
 
        } else { $logfile = "$logfile"; }
 
-       $actfile = $config->bootstrap->actlog;
-       if($actfile =~ /^syslog/) {
-               $act_syslog_enabled = 1;
-               $act_logfile_enabled = 0;
-               $actfile =~ s/^syslog:?//;
-               $actfac = $actfile || "local1";
-               $actfile = undef;
-               $actfac = _fac_to_const($actfac);
 
-       } else { $actfile = "$actfile"; }
+    if($syslog_enabled) {
+        # --------------------------------------------------------------
+        # if we're syslogging, see if we have a special syslog facility 
+        # for activity logging.  If not, use the syslog facility for
+        # standard logging
+        # --------------------------------------------------------------
+        $act_syslog_enabled = 1;
+        $act_logfile_enabled = 0;
+        $actfac = $config->bootstrap->actlog || $config->bootstrap->syslog;
+        $actfac = _fac_to_const($actfac);
+        $actfile = undef;
+    } else {
+        # --------------------------------------------------------------
+        # we're not syslogging, use any specified activity log file.
+        # Fall back to the standard log file otherwise
+        # --------------------------------------------------------------
+               $act_syslog_enabled = 0;
+               $act_logfile_enabled = 1;
+        $actfile = $config->bootstrap->actlog || $config->bootstrap->logfile;
+    }
+
 
        $isclient = (OpenSRF::Utils::Config->current->bootstrap->client =~ /^true$/iog) ?  1 : 0;
 }
index 34e8df3..74f8bd9 100644 (file)
 
 from osrf.utils import *
 from osrf.ex import *
+import re
 
 class osrfConfig(object):
-       """Loads and parses the bootstrap config file"""
+    """Loads and parses the bootstrap config file"""
 
-       config = None
+    config = None
 
-       def __init__(self, file=None):
-               self.file = file        
-               self.data = {}
+    def __init__(self, file, context=None):
+        self.file = file    
+        self.context = context
+        self.data = {}
 
-       def parseConfig(self,file=None):
-               self.data = osrfXMLFileToObject(file or self.file)
-               osrfConfig.config = self
-       
-       def getValue(self, key, idx=None):
-               val = osrfObjectFindPath(self.data, key, idx)
-               if not val:
-                       raise osrfConfigException("Config value not found: " + key)
-               return val
+    #def parseConfig(self,file=None):
+    def parseConfig(self):
+        self.data = osrfXMLFileToObject(self.file)
+        osrfConfig.config = self
+    
+    def getValue(self, key, idx=None):
+        if self.context:
+            if re.search('/', key):
+                key = "%s/%s" % (self.context, key)
+            else:
+                key = "%s.%s" % (self.context, key)
+
+        val = osrfObjectFindPath(self.data, key, idx)
+        if not val:
+            raise osrfConfigException("Config value not found: " + key)
+        return val
 
 
 def osrfConfigValue(key, idx=None):
-       """Returns a bootstrap config value.
-
-       key -- A string representing the path to the value in the config object
-               e.g.  "domains.domain", "username"
-       idx -- Optional array index if the searched value is an array member
-       """
-       return osrfConfig.config.getValue(key, idx)
-                               
+    """Returns a bootstrap config value.
+
+    key -- A string representing the path to the value in the config object
+        e.g.  "domains.domain", "username"
+    idx -- Optional array index if the searched value is an array member
+    """
+    return osrfConfig.config.getValue(key, idx)
+                
+
+def osrfConfigValueNoEx(key, idx=None):
+    """ Returns a bootstrap config value without throwing an exception
+        if the item is not found. 
+
+    key -- A string representing the path to the value in the config object
+        e.g.  "domains.domain", "username"
+    idx -- Optional array index if the searched value is an array member
+    """
+    try:
+        return osrfConfig.config.getValue(key, idx)
+    except:
+        return None
+
index c9f9392..98c8686 100644 (file)
@@ -21,7 +21,7 @@ class GatewayRequest:
             response =urllib2.urlopen(request)
         except urllib2.HTTPError, e:
             # log this?
-            sys.stderr.write('HTTPError: code=%d : %s' % (e.code, str(e)))
+            sys.stderr.write('%s => %s?%s\n' % (str(e), self.buildURL(), params))
             raise e
             
         return self.handleResponse(response)
@@ -77,6 +77,9 @@ class XMLGatewayParser(handler.ContentHandler):
         self.keyStack = []
         self.posStack = [] # for tracking array-based hinted object indices
 
+        # true if we are parsing an element that may have character data
+        self.charsPending = 0 
+
     def getResult(self):
         return self.result
 
@@ -87,13 +90,20 @@ class XMLGatewayParser(handler.ContentHandler):
         return None
 
     def startElement(self, name, attrs):
-
-        # XXX add support for serializable objects!
+        
+        if self.charsPending:
+            # we just read a 'string' or 'number' element that resulted
+            # in no text data.  Appaned a None object
+            self.appendChild(None)
 
         if name == 'null':
             self.appendChild(None)
             return
 
+        if name == 'string' or name == 'number':
+            self.charsPending = True
+            return
+
         if name == 'element': # this is an object item wrapper
             self.keyStack.append(self.__getAttr(attrs, 'key'))
             return
@@ -157,6 +167,7 @@ class XMLGatewayParser(handler.ContentHandler):
             self.objStack.pop()
 
     def characters(self, chars):
+        self.charsPending = False
         self.appendChild(urllib.unquote_plus(chars))
 
 
index b6b3154..8845b92 100644 (file)
@@ -6,7 +6,7 @@ class osrfJSONNetworkEncoder(simplejson.JSONEncoder):
     def default(self, obj):
         if isinstance(obj, osrfNetworkObject):
             return { 
-                OSRF_JSON_CLASS_KEY: obj.getHint(),
+                OSRF_JSON_CLASS_KEY: obj.getRegistry().hint,
                 OSRF_JSON_PAYLOAD_KEY: self.default(obj.getData())
             }   
         return obj
index f0ef2ad..187a34d 100644 (file)
@@ -22,9 +22,14 @@ def osrfInitLog(level, facility=None, file=None):
     """Initialize the logging subsystem."""
     import syslog
     global loglevel
-    if facility: osrfInitSyslog(facility, level)
+    if facility: 
+        osrfInitSyslog(facility, level)
+        syslog.syslog(syslog.LOG_DEBUG, "syslog initialized")
+    else:
+        if file:
+            sys.stderr.write("\n * file-based logging not implemented yet\n")
+            
     loglevel = level
-    syslog.syslog(LOG_DEBUG, "syslog initialized")
 
 
 # -----------------------------------------------------------------------
@@ -72,6 +77,8 @@ def __osrfLog(level, msg):
 def osrfInitSyslog(facility, level):
     """Connect to syslog and set the logmask based on the level provided."""
 
+    import syslog
+
     level = int(level)
 
     if facility == 'local0': facility = syslog.LOG_LOCAL0
@@ -82,13 +89,13 @@ def osrfInitSyslog(facility, level):
     if facility == 'local5': facility = syslog.LOG_LOCAL5
     if facility == 'local6': facility = syslog.LOG_LOCAL6
     # XXX add other facility maps if necessary
-    openlog(sys.argv[0], 0, facility)
+    syslog.openlog(sys.argv[0], 0, facility)
 
     # this is redundant...
-    mask = LOG_UPTO(syslog.LOG_ERR)
-    if level >= 1: mask |= LOG_MASK(syslog.LOG_WARNING)
-    if level >= 2: mask |= LOG_MASK(syslog.LOG_NOTICE)
-    if level >= 3: mask |= LOG_MASK(syslog.LOG_INFO)
-    if level >= 4: mask |= LOG_MASK(syslog.LOG_DEBUG)
+    mask = syslog.LOG_UPTO(syslog.LOG_ERR)
+    if level >= 1: mask |= syslog.LOG_MASK(syslog.LOG_WARNING)
+    if level >= 2: mask |= syslog.LOG_MASK(syslog.LOG_NOTICE)
+    if level >= 3: mask |= syslog.LOG_MASK(syslog.LOG_INFO)
+    if level >= 4: mask |= syslog.LOG_MASK(syslog.LOG_DEBUG)
     syslog.setlogmask(mask)
 
index 792c613..8ae3b9b 100644 (file)
@@ -13,7 +13,6 @@ def osrfNewObjectFromHint(hint):
         return obj
     except AttributeError:
         return osrfNetworkObject.__unknown()
-#newFromHint = staticmethod(newFromHint)
 
 
 ''' Global object registry '''
@@ -76,9 +75,8 @@ def __osrfNetworkObjectInit(self, data={}):
         If this is an array, we pull data out of the data array
         (if there is any) and translate that into a hash internally
         '''
-
     self.__data = data
-    if len(data) > 0:
+    if isinstance(data, list) and len(data) > 0:
         reg = self.getRegistry()
         if reg.wireProtocol == 'array':
             self.__data = {}
@@ -134,31 +132,47 @@ osrfNetworkRegisterHint('__unknown', [], 'hash')
 # Define the custom object parsing behavior 
 # -------------------------------------------------------------------
 def parseNetObject(obj):
-    hint = None
-    islist = False
+    
     try:
+
         hint = obj[OSRF_JSON_CLASS_KEY]
-        obj = obj[OSRF_JSON_PAYLOAD_KEY]
-    except: pass
-    if isinstance(obj,list):
-        islist = True
-        for i in range(len(obj)):
-            obj[i] = parseNetObject(obj[i])
-    else: 
-        if isinstance(obj,dict):
-            for k,v in obj.iteritems():
-                obj[k] = parseNetObject(v)
+        subObj = obj[OSRF_JSON_PAYLOAD_KEY]
+        reg = osrfNetworkRegistry.getRegistry(hint)
+
+        obj = {}
+
+        if reg.wireProtocol == 'array':
+            for i in range(len(reg.keys)):
+                if len(subObj) > i:
+                    obj[reg.keys[i]] = parseNetObject(subObj[i])
+                else:
+                    obj[reg.keys[i]] = None
+        else:
+            for k in reg.keys:
+                obj[k] = parseNetObject(subObj.get(k))
 
-    if hint: # Now, "bless" the object into an osrfNetworkObject
         estr = 'obj = osrfNetworkObject.%s(obj)' % hint
         try:
             exec(estr)
-        except AttributeError:
+        except e:
             # this object has not been registered, shove it into the default container
             obj = osrfNetworkObject.__unknown(obj)
 
-    return obj;
+        return obj
+
+    except: pass
+
+    # the current object does not have a class hint
+    if isinstance(obj, list):
+        for i in range(len(obj)):
+            obj[i] = parseNetObject(obj[i])
+
+    else:
+        if isinstance(obj, dict):
+            for k,v in obj.iteritems():
+                obj[k] = parseNetObject(v)
 
+    return obj;
 
 
 def osrfObjectToXML(obj):
index f1c6c38..462ae08 100644 (file)
@@ -33,276 +33,276 @@ osrfNetworkRegisterHint('osrfMethodException', ['status', 'statusCode'], 'hash')
 
 
 class osrfSession(object):
-       """Abstract session superclass."""
+    """Abstract session superclass."""
 
-       def __init__(self):
-               # by default, we're connected to no one
-               self.state = OSRF_APP_SESSION_DISCONNECTED
+    def __init__(self):
+        # by default, we're connected to no one
+        self.state = OSRF_APP_SESSION_DISCONNECTED
 
 
-       def wait(self, timeout=120):
-               """Wait up to <timeout> seconds for data to arrive on the network"""
-               osrfLogInternal("osrfSession.wait(%d)" % timeout)
-               handle = osrfGetNetworkHandle()
-               handle.recv(timeout)
+    def wait(self, timeout=120):
+        """Wait up to <timeout> seconds for data to arrive on the network"""
+        osrfLogInternal("osrfSession.wait(%d)" % timeout)
+        handle = osrfGetNetworkHandle()
+        handle.recv(timeout)
 
-       def send(self, omessage):
-               """Sends an OpenSRF message"""
-               netMessage = osrfNetworkMessage(
-                       to              = self.remoteId,
-                       body    = osrfObjectToJSON([omessage]),
-                       thread = self.thread )
+    def send(self, omessage):
+        """Sends an OpenSRF message"""
+        netMessage = osrfNetworkMessage(
+            to      = self.remoteId,
+            body    = osrfObjectToJSON([omessage]),
+            thread = self.thread )
 
-               handle = osrfGetNetworkHandle()
-               handle.send(netMessage)
+        handle = osrfGetNetworkHandle()
+        handle.send(netMessage)
 
-       def cleanup(self):
-               """Removes the session from the global session cache."""
-               del osrfClientSession.sessionCache[self.thread]
+    def cleanup(self):
+        """Removes the session from the global session cache."""
+        del osrfClientSession.sessionCache[self.thread]
 
 class osrfClientSession(osrfSession):
-       """Client session object.  Use this to make server requests."""
-
-       def __init__(self, service):
-               
-               # call superclass constructor
-               osrfSession.__init__(self)
-
-               # the remote service we want to make requests of
-               self.service = service
-
-               # find the remote service handle <router>@<domain>/<service>
-               domain = osrfConfigValue('domains.domain', 0)
-               router = osrfConfigValue('router_name')
-               self.remoteId = "%s@%s/%s" % (router, domain, service)
-               self.origRemoteId = self.remoteId
-
-               # generate a random message thread
-               self.thread = "%s%s%s" % (os.getpid(), str(random.randint(100,100000)), str(time.time()))
-
-               # how many requests this session has taken part in
-               self.nextId = 0 
-
-               # cache of request objects 
-               self.requests = {}
-
-               # cache this session in the global session cache
-               osrfClientSession.sessionCache[self.thread] = self
-
-       def resetRequestTimeout(self, rid):
-               req = self.findRequest(rid)
-               if req:
-                       req.resetTimeout = True
-                       
-
-       def request2(self, method, arr):
-               """Creates a new request and sends the request to the server using a python array as the params."""
-               return self.__request(method, arr)
-
-       def request(self, method, *args):
-               """Creates a new request and sends the request to the server using a variable argument list as params"""
-               arr = list(args)
-               return self.__request(method, arr)
-
-       def __request(self, method, arr):
-               """Builds the request object and sends it."""
-               if self.state != OSRF_APP_SESSION_CONNECTED:
-                       self.resetRemoteId()
-
-               osrfLogDebug("Sending request %s -> %s " % (self.service, method))
-               req = osrfRequest(self, self.nextId, method, arr)
-               self.requests[str(self.nextId)] = req
-               self.nextId += 1
-               req.send()
-               return req
-
-
-       def connect(self, timeout=10):
-               """Connects to a remote service"""
-
-               if self.state == OSRF_APP_SESSION_CONNECTED:
-                       return True
-               self.state == OSRF_APP_SESSION_CONNECTING
-
-               # construct and send a CONNECT message
-               self.send(
-                       osrfNetworkObject.osrfMessage( 
-                               {       'threadTrace' : 0,
-                                       'type' : OSRF_MESSAGE_TYPE_CONNECT
-                               
-                       )
-               )
-
-               while timeout >= 0 and not self.state == OSRF_APP_SESSION_CONNECTED:
-                       start = time.time()
-                       self.wait(timeout)
-                       timeout -= time.time() - start
-               
-               if self.state != OSRF_APP_SESSION_CONNECTED:
-                       raise osrfServiceException("Unable to connect to " + self.service)
-               
-               return True
-
-       def disconnect(self):
-               """Disconnects from a remote service"""
-
-               if self.state == OSRF_APP_SESSION_DISCONNECTED:
-                       return True
-
-               self.send(
-                       osrfNetworkObject.osrfMessage( 
-                               {       'threadTrace' : 0,
-                                       'type' : OSRF_MESSAGE_TYPE_DISCONNECT
-                               
-                       )
-               )
-
-               self.state = OSRF_APP_SESSION_DISCONNECTED
-
-
-               
-       
-       def setRemoteId(self, remoteid):
-               self.remoteId = remoteid
-               osrfLogInternal("Setting request remote ID to %s" % self.remoteId)
-
-       def resetRemoteId(self):
-               """Recovers the original remote id"""
-               self.remoteId = self.origRemoteId
-               osrfLogInternal("Resetting remote ID to %s" % self.remoteId)
-
-       def pushResponseQueue(self, message):
-               """Pushes the message payload onto the response queue 
-                       for the request associated with the message's ID."""
-               osrfLogDebug("pushing %s" % message.payload())
-               try:
-                       self.findRequest(message.threadTrace()).pushResponse(message.payload())
-               except Exception, e: 
-                       osrfLogWarn("pushing respond to non-existent request %s : %s" % (message.threadTrace(), e))
-
-       def findRequest(self, rid):
-               """Returns the original request matching this message's threadTrace."""
-               try:
-                       return self.requests[str(rid)]
-               except KeyError:
-                       osrfLogDebug('findRequest(): non-existent request %s' % str(rid))
-                       return None
+    """Client session object.  Use this to make server requests."""
+
+    def __init__(self, service):
+        
+        # call superclass constructor
+        osrfSession.__init__(self)
+
+        # the remote service we want to make requests of
+        self.service = service
+
+        # find the remote service handle <router>@<domain>/<service>
+        domain = osrfConfigValue('domains.domain', 0)
+        router = osrfConfigValue('router_name')
+        self.remoteId = "%s@%s/%s" % (router, domain, service)
+        self.origRemoteId = self.remoteId
+
+        # generate a random message thread
+        self.thread = "%s%s%s" % (os.getpid(), str(random.randint(100,100000)), str(time.time()))
+
+        # how many requests this session has taken part in
+        self.nextId = 0 
+
+        # cache of request objects 
+        self.requests = {}
+
+        # cache this session in the global session cache
+        osrfClientSession.sessionCache[self.thread] = self
+
+    def resetRequestTimeout(self, rid):
+        req = self.findRequest(rid)
+        if req:
+            req.resetTimeout = True
+            
+
+    def request2(self, method, arr):
+        """Creates a new request and sends the request to the server using a python array as the params."""
+        return self.__request(method, arr)
+
+    def request(self, method, *args):
+        """Creates a new request and sends the request to the server using a variable argument list as params"""
+        arr = list(args)
+        return self.__request(method, arr)
+
+    def __request(self, method, arr):
+        """Builds the request object and sends it."""
+        if self.state != OSRF_APP_SESSION_CONNECTED:
+            self.resetRemoteId()
+
+        osrfLogDebug("Sending request %s -> %s " % (self.service, method))
+        req = osrfRequest(self, self.nextId, method, arr)
+        self.requests[str(self.nextId)] = req
+        self.nextId += 1
+        req.send()
+        return req
+
+
+    def connect(self, timeout=10):
+        """Connects to a remote service"""
+
+        if self.state == OSRF_APP_SESSION_CONNECTED:
+            return True
+        self.state == OSRF_APP_SESSION_CONNECTING
+
+        # construct and send a CONNECT message
+        self.send(
+            osrfNetworkObject.osrfMessage( 
+                {   'threadTrace' : 0,
+                    'type' : OSRF_MESSAGE_TYPE_CONNECT
+                } 
+            )
+        )
+
+        while timeout >= 0 and not self.state == OSRF_APP_SESSION_CONNECTED:
+            start = time.time()
+            self.wait(timeout)
+            timeout -= time.time() - start
+        
+        if self.state != OSRF_APP_SESSION_CONNECTED:
+            raise osrfServiceException("Unable to connect to " + self.service)
+        
+        return True
+
+    def disconnect(self):
+        """Disconnects from a remote service"""
+
+        if self.state == OSRF_APP_SESSION_DISCONNECTED:
+            return True
+
+        self.send(
+            osrfNetworkObject.osrfMessage( 
+                {   'threadTrace' : 0,
+                    'type' : OSRF_MESSAGE_TYPE_DISCONNECT
+                } 
+            )
+        )
+
+        self.state = OSRF_APP_SESSION_DISCONNECTED
+
+
+        
+    
+    def setRemoteId(self, remoteid):
+        self.remoteId = remoteid
+        osrfLogInternal("Setting request remote ID to %s" % self.remoteId)
+
+    def resetRemoteId(self):
+        """Recovers the original remote id"""
+        self.remoteId = self.origRemoteId
+        osrfLogInternal("Resetting remote ID to %s" % self.remoteId)
+
+    def pushResponseQueue(self, message):
+        """Pushes the message payload onto the response queue 
+            for the request associated with the message's ID."""
+        osrfLogDebug("pushing %s" % message.payload())
+        try:
+            self.findRequest(message.threadTrace()).pushResponse(message.payload())
+        except Exception, e: 
+            osrfLogWarn("pushing respond to non-existent request %s : %s" % (message.threadTrace(), e))
+
+    def findRequest(self, rid):
+        """Returns the original request matching this message's threadTrace."""
+        try:
+            return self.requests[str(rid)]
+        except KeyError:
+            osrfLogDebug('findRequest(): non-existent request %s' % str(rid))
+            return None
 
 
 
 osrfSession.sessionCache = {}
 def osrfFindSession(thread):
-       """Finds a session in the global cache."""
-       try:
-               return osrfClientSession.sessionCache[thread]
-       except: return None
+    """Finds a session in the global cache."""
+    try:
+        return osrfClientSession.sessionCache[thread]
+    except: return None
 
 class osrfRequest(object):
-       """Represents a single OpenSRF request.
-               A request is made and any resulting respones are 
-               collected for the client."""
-
-       def __init__(self, session, id, method=None, params=[]):
-
-               self.session = session # my session handle
-               self.id         = id # my unique request ID
-               self.method = method # method name
-               self.params = params # my method params
-               self.queue      = [] # response queue
-               self.resetTimeout = False # resets the recv timeout?
-               self.complete = False # has the server told us this request is done?
-               self.sendTime = 0 # local time the request was put on the wire
-               self.completeTime =  0 # time the server told us the request was completed
-               self.firstResponseTime = 0 # time it took for our first reponse to be received
-
-       def send(self):
-               """Sends a request message"""
-
-               # construct the method object message with params and method name
-               method = osrfNetworkObject.osrfMethod( {
-                       'method' : self.method,
-                       'params' : self.params
-               } )
-
-               # construct the osrf message with our method message embedded
-               message = osrfNetworkObject.osrfMessage( {
-                       'threadTrace' : self.id,
-                       'type' : OSRF_MESSAGE_TYPE_REQUEST,
-                       'payload' : method
-               } )
-
-               self.sendTime = time.time()
-               self.session.send(message)
-
-       def recv(self, timeout=120):
-               """Waits up to <timeout> seconds for a response to this request.
-               
-                       If a message is received in time, the response message is returned.
-                       Returns None otherwise."""
-
-               self.session.wait(0)
-
-               origTimeout = timeout
-               while not self.complete and timeout >= 0 and len(self.queue) == 0:
-                       s = time.time()
-                       self.session.wait(timeout)
-                       timeout -= time.time() - s
-                       if self.resetTimeout:
-                               self.resetTimeout = False
-                               timeout = origTimeout
-
-               now = time.time()
-
-               # -----------------------------------------------------------------
-               # log some statistics 
-               if len(self.queue) > 0:
-                       if not self.firstResponseTime:
-                               self.firstResponseTime = now
-                               osrfLogDebug("time elapsed before first response: %f" \
-                                       % (self.firstResponseTime - self.sendTime))
-
-               if self.complete:
-                       if not self.completeTime:
-                               self.completeTime = now
-                               osrfLogDebug("time elapsed before complete: %f" \
-                                       % (self.completeTime - self.sendTime))
-               # -----------------------------------------------------------------
-
-
-               if len(self.queue) > 0:
-                       # we have a reponse, return it
-                       return self.queue.pop(0)
-
-               return None
-
-       def pushResponse(self, content):
-               """Pushes a method response onto this requests response queue."""
-               self.queue.append(content)
-
-       def cleanup(self):
-               """Cleans up request data from the cache. 
-
-                       Do this when you are done with a request to prevent "leaked" cache memory."""
-               del self.session.requests[str(self.id)]
-
-       def setComplete(self):
-               """Sets me as complete.  This means the server has sent a 'request complete' message"""
-               self.complete = True
+    """Represents a single OpenSRF request.
+        A request is made and any resulting respones are 
+        collected for the client."""
+
+    def __init__(self, session, id, method=None, params=[]):
+
+        self.session = session # my session handle
+        self.id     = id # my unique request ID
+        self.method = method # method name
+        self.params = params # my method params
+        self.queue  = [] # response queue
+        self.resetTimeout = False # resets the recv timeout?
+        self.complete = False # has the server told us this request is done?
+        self.sendTime = 0 # local time the request was put on the wire
+        self.completeTime =  0 # time the server told us the request was completed
+        self.firstResponseTime = 0 # time it took for our first reponse to be received
+
+    def send(self):
+        """Sends a request message"""
+
+        # construct the method object message with params and method name
+        method = osrfNetworkObject.osrfMethod( {
+            'method' : self.method,
+            'params' : self.params
+        } )
+
+        # construct the osrf message with our method message embedded
+        message = osrfNetworkObject.osrfMessage( {
+            'threadTrace' : self.id,
+            'type' : OSRF_MESSAGE_TYPE_REQUEST,
+            'payload' : method
+        } )
+
+        self.sendTime = time.time()
+        self.session.send(message)
+
+    def recv(self, timeout=120):
+        """Waits up to <timeout> seconds for a response to this request.
+        
+            If a message is received in time, the response message is returned.
+            Returns None otherwise."""
+
+        self.session.wait(0)
+
+        origTimeout = timeout
+        while not self.complete and timeout >= 0 and len(self.queue) == 0:
+            s = time.time()
+            self.session.wait(timeout)
+            timeout -= time.time() - s
+            if self.resetTimeout:
+                self.resetTimeout = False
+                timeout = origTimeout
+
+        now = time.time()
+
+        # -----------------------------------------------------------------
+        # log some statistics 
+        if len(self.queue) > 0:
+            if not self.firstResponseTime:
+                self.firstResponseTime = now
+                osrfLogDebug("time elapsed before first response: %f" \
+                    % (self.firstResponseTime - self.sendTime))
+
+        if self.complete:
+            if not self.completeTime:
+                self.completeTime = now
+                osrfLogDebug("time elapsed before complete: %f" \
+                    % (self.completeTime - self.sendTime))
+        # -----------------------------------------------------------------
+
+
+        if len(self.queue) > 0:
+            # we have a reponse, return it
+            return self.queue.pop(0)
+
+        return None
+
+    def pushResponse(self, content):
+        """Pushes a method response onto this requests response queue."""
+        self.queue.append(content)
+
+    def cleanup(self):
+        """Cleans up request data from the cache. 
+
+            Do this when you are done with a request to prevent "leaked" cache memory."""
+        del self.session.requests[str(self.id)]
+
+    def setComplete(self):
+        """Sets me as complete.  This means the server has sent a 'request complete' message"""
+        self.complete = True
 
 
 class osrfServerSession(osrfSession):
-       """Implements a server-side session"""
-       pass
+    """Implements a server-side session"""
+    pass
 
 
 def osrfAtomicRequest(service, method, *args):
-       ses = osrfClientSession(service)
-       req = ses.request2('open-ils.cstore.direct.actor.user.retrieve', list(args)) # grab user with ID 1
-       resp = req.recv()
-       data = resp.content()
-       req.cleanup()
-       ses.cleanup()
-       return data
+    ses = osrfClientSession(service)
+    req = ses.request2(method, list(args))
+    resp = req.recv()
+    data = resp.content()
+    req.cleanup()
+    ses.cleanup()
+    return data
 
 
 
index 4a978a5..bfc5463 100644 (file)
@@ -13,7 +13,7 @@
 # GNU General Public License for more details.
 # -----------------------------------------------------------------------
 
-from osrf.conf import osrfConfig, osrfConfigValue
+from osrf.conf import osrfConfig, osrfConfigValue, osrfConfigValueNoEx
 from osrf.net import osrfNetwork, osrfSetNetworkHandle
 from osrf.stack import osrfPushStack
 from osrf.log import *
@@ -21,28 +21,31 @@ from osrf.set import osrfLoadSettings
 import sys
 
 
-def osrfConnect(configFile):
-       """ Connects to the opensrf network """
-
-       # parse the config file
-       configParser = osrfConfig(configFile)
-       configParser.parseConfig()
-       
-       # set up logging
-       osrfInitLog(osrfConfigValue('loglevel'), osrfConfigValue('syslog'))
-
-       # connect to the opensrf network
-       network = osrfNetwork(
-               host=osrfConfigValue('domains.domain'),
-               port=osrfConfigValue('port'),
-               username=osrfConfigValue('username'), 
-               password=osrfConfigValue('passwd'))
-       network.setRecvCallback(osrfPushStack)
-       osrfSetNetworkHandle(network)
-       network.connect()
-
-       # load the domain-wide settings file
-       osrfLoadSettings(osrfConfigValue('domains.domain'))
+def osrfConnect(configFile, configContext):
+    """ Connects to the opensrf network """
+
+    # parse the config file
+    configParser = osrfConfig(configFile, configContext)
+    configParser.parseConfig()
+    
+    # set up logging
+    osrfInitLog(
+        osrfConfigValue('loglevel'), 
+        osrfConfigValueNoEx('syslog'),
+        osrfConfigValueNoEx('logfile'))
+
+    # connect to the opensrf network
+    network = osrfNetwork(
+        host=osrfConfigValue('domains.domain'),
+        port=osrfConfigValue('port'),
+        username=osrfConfigValue('username'), 
+        password=osrfConfigValue('passwd'))
+    network.setRecvCallback(osrfPushStack)
+    osrfSetNetworkHandle(network)
+    network.connect()
+
+    # load the domain-wide settings file
+    osrfLoadSettings(osrfConfigValue('domains.domain'))
 
 
 
index fe637f1..6b20675 100644 (file)
@@ -3,14 +3,14 @@ import xml.dom.minidom, re
 def osrfXMLFileToObject(filename):
     """Turns the contents of an XML file into a Python object"""
     doc = xml.dom.minidom.parse(filename)
-    obj = osrfXMLNodeToObject(doc.childNodes[0])
+    obj = osrfXMLNodeToObject(doc.documentElement)
     doc.unlink()
     return obj
 
 def osrfXMLStringToObject(string):
     """Turns an XML string into a Python object"""
     doc = xml.dom.minidom.parseString(string)
-    obj = osrfXMLNodeToObject(doc.childNodes[0])
+    obj = osrfXMLNodeToObject(doc.documentElement)
     doc.unlink()
     return obj
 
@@ -72,7 +72,7 @@ def osrfObjectFindPath(obj, path, idx=None):
 
     parts = []
 
-    if re.compile('/').search(path):
+    if re.search('/', path):
         parts = path.split('/')
     else:
         parts = path.split('.')
index 4742246..70a278e 100755 (executable)
@@ -214,9 +214,8 @@ def setup_readline():
 
 def do_connect():
        file = os.path.join(get_var('HOME'), ".srfsh.xml")
-
        print_green("Connecting to opensrf...")
-       osrfConnect(file)
+       osrfConnect(file, 'srfsh')
        print_red('OK\n')
 
 def load_plugins():
index f3122cb..a789d98 100644 (file)
@@ -35,12 +35,9 @@ int main( int argc, char* argv[] ) {
 
 int __setupRouter( char* config, char* context ) {
 
-       osrfLogInfo(OSRF_LOG_MARK, "Launching router with config "
-                       "%s and config context %s", config, context );
        osrfConfig* cfg = osrfConfigInit( config, context );
        osrfConfigSetDefaultConfig(cfg);
 
-
        char* server                    = osrfConfigGetValue(NULL, "/transport/server");
        char* port                              = osrfConfigGetValue(NULL, "/transport/port");
        char* username                  = osrfConfigGetValue(NULL, "/transport/username");
@@ -55,11 +52,6 @@ int __setupRouter( char* config, char* context ) {
        int llevel = 1;
        if(level) llevel = atoi(level);
 
-       /*
-       if(!log_init( llevel, log_file )) 
-               fprintf(stderr, "Unable to init logging, going to stderr...\n" );
-               */
-
        if(!log_file) { fprintf(stderr, "Log file needed\n"); return -1; }
 
        if(!strcmp(log_file, "syslog")) {
index 163818e..9b04bd5 100644 (file)
@@ -6,7 +6,7 @@ LDFLAGS += -DEXEC_DEFAULT
 all: srfsh
 
 srfsh: srfsh.o
-srfsh.o:       srfsh.c srfsh.h
+srfsh.o:       srfsh.c 
 
 install: 
        cp srfsh $(BINDIR)
index 9887038..6c4cb54 100644 (file)
@@ -1,9 +1,77 @@
-#include "srfsh.h"
+#include <opensrf/transport_client.h>
+#include <opensrf/osrf_message.h>
+#include <opensrf/osrf_app_session.h>
+#include <time.h>
+#include <ctype.h>
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 
-int recv_timeout = 120;
-int is_from_script = 0;
-FILE* shell_writer = NULL;
-FILE* shell_reader = NULL;
+#include <opensrf/utils.h>
+#include <opensrf/log.h>
+
+#include <signal.h>
+
+#include <stdio.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#define SRFSH_PORT 5222
+#define COMMAND_BUFSIZE 4096
+
+
+/* shell prompt */
+static const char* prompt = "srfsh# ";
+
+static char* history_file = NULL;
+
+//static int child_dead = 0;
+
+static char* login_session = NULL;
+
+/* true if we're pretty printing json results */
+static int pretty_print = 1;
+/* true if we're bypassing 'less' */
+static int raw_print = 0;
+
+/* our jabber connection */
+static transport_client* client = NULL; 
+
+/* the last result we received */
+static osrf_message* last_result = NULL;
+
+/* functions */
+static int parse_request( char* request );
+
+/* handles router requests */
+static int handle_router( char* words[] );
+
+/* utility method for print time data */
+/* static int handle_time( char* words[] ); */
+
+/* handles app level requests */
+static int handle_request( char* words[], int relay );
+static int handle_set( char* words[]);
+static int handle_print( char* words[]);
+static int send_request( char* server, 
+                                 char* method, growing_buffer* buffer, int relay );
+static int parse_error( char* words[] );
+static int router_query_servers( const char* server );
+static int print_help( void );
+
+//static int srfsh_client_connect();
+//static char* tabs(int count);
+//static void sig_child_handler( int s );
+//static void sig_int_handler( int s );
+
+static int load_history( void );
+static int handle_math( char* words[] );
+static int do_math( int count, int style );
+static int handle_introspect(char* words[]);
+static int handle_login( char* words[]);
+
+static int recv_timeout = 120;
+static int is_from_script = 0;
 
 int main( int argc, char* argv[] ) {
 
@@ -50,32 +118,66 @@ int main( int argc, char* argv[] ) {
 
        client = osrf_system_get_transport_client();
 
-       /* open the shell handle */
-       shell_writer = popen( "bash", "w");
-       //shell_reader = popen( "bash", "r");
-
        /* main process loop */
+       int newline_needed = 1;  /* used as boolean */
        char* request;
        while((request=readline(prompt))) {
 
-               if( !strcasecmp(request, "exit") || !strcasecmp(request,"quit")) 
-                       break; 
+               // Find first non-whitespace character
+               
+               char * cmd = request;
+               while( isspace( (unsigned char) *cmd ) )
+                       ++cmd;
 
-               char* req_copy = strdup(request);
+               // ignore comments and empty lines
+
+               if( '\0' == *cmd || '#' == *cmd )
+                       continue;
+
+               // Remove trailing whitespace.  We know at this point that
+               // there is at least one non-whitespace character somewhere,
+               // or we would have already skipped this line.  Hence we
+               // needn't check to make sure that we don't back up past
+               // the beginning.
+
+               {
+                       // The curly braces limit the scope of the end variable
+                       
+                       char * end = cmd + strlen(cmd) - 1;
+                       while( isspace( (unsigned char) *end ) )
+                               --end;
+                       end[1] = '\0';
+               }
+
+               if( !strcasecmp(cmd, "exit") || !strcasecmp(cmd, "quit"))
+               {
+                       newline_needed = 0;
+                       break; 
+               }
+               
+               char* req_copy = strdup(cmd);
 
                parse_request( req_copy ); 
-               if( request && strlen(request) > 1 ) {
+               if( request && *cmd ) {
                        add_history(request);
                }
 
                free(request);
                free(req_copy);
 
-               fflush(shell_writer);
                fflush(stderr);
                fflush(stdout);
        }
 
+       if( newline_needed ) {
+               
+               // We left the readline loop after seeing an EOF, not after
+               // seeing "quit" or "exit".  So we issue a newline in order
+               // to avoid leaving a dangling prompt.
+
+               putchar( '\n' );
+       }
+
        if(history_file != NULL )
                write_history(history_file);
 
@@ -85,9 +187,11 @@ int main( int argc, char* argv[] ) {
        return 0;
 }
 
-void sig_child_handler( int s ) {
+/*
+static void sig_child_handler( int s ) {
        child_dead = 1;
 }
+*/
 
 /*
 void sig_int_handler( int s ) {
@@ -97,7 +201,7 @@ void sig_int_handler( int s ) {
 }
 */
 
-int load_history() {
+static int load_history( void ) {
 
        char* home = getenv("HOME");
        int l = strlen(home) + 24;
@@ -115,54 +219,62 @@ int load_history() {
 }
 
 
-int parse_error( char* words[] ) {
+static int parse_error( char* words[] ) {
 
        if( ! words )
                return 0;
 
-
-       int i = 0;
-       char* current;
-       char buffer[256];
-       memset(buffer, 0, 256);
-       while( (current=words[i++]) ) {
-               strcat(buffer, current);
-               strcat(buffer, " ");
+       growing_buffer * gbuf = buffer_init( 64 );
+       buffer_add( gbuf, *words );
+       while( *++words ) {
+               buffer_add( gbuf, " " );
+               buffer_add( gbuf, *words );
        }
-       if( ! buffer || strlen(buffer) < 1 ) 
-               printf("\n");
-
-       fprintf( stderr, "???: %s\n", buffer );
+       fprintf( stderr, "???: %s\n", gbuf->buf );
+       buffer_free( gbuf );
+       
        return 0;
 
 }
 
 
-int parse_request( char* request ) {
+static int parse_request( char* request ) {
 
        if( request == NULL )
                return 0;
 
+       char* original_request = strdup( request );
+       char* words[COMMAND_BUFSIZE]; 
+       
        int ret_val = 0;
        int i = 0;
-       char* words[COMMAND_BUFSIZE]; 
-       memset(words,0,COMMAND_BUFSIZE);
-       char* req = request;
 
+
+       char* req = request;
        char* cur_tok = strtok( req, " " );
 
        if( cur_tok == NULL )
+       {
+               free( original_request );
                return 0;
+       }
 
+       /* Load an array with pointers to    */
+       /* the tokens as defined by strtok() */
+       
        while(cur_tok != NULL) {
-               words[i++] = cur_tok;
-               cur_tok = strtok( NULL, " " );
+               if( i < COMMAND_BUFSIZE - 1 ) {
+                       words[i++] = cur_tok;
+                       cur_tok = strtok( NULL, " " );
+               } else {
+                       fprintf( stderr, "Too many tokens in command\n" );
+                       free( original_request );
+                       return 1;
+               }
        }
 
-
-       // not sure why (strtok?), but this is necessary
-       memset( words + i, 0, COMMAND_BUFSIZE - i );
-
+       words[i] = NULL;
+       
        /* pass off to the top level command */
        if( !strcmp(words[0],"router") ) 
                ret_val = handle_router( words );
@@ -196,47 +308,50 @@ int parse_request( char* request ) {
        else if (!strcmp(words[0],"login"))
                ret_val = handle_login(words);
 
-       else if (words[0][0] == '!')
-               ret_val = handle_exec( words, 1 );
-
-       if(!ret_val) {
-               #ifdef EXEC_DEFAULT
-                       return handle_exec( words, 0 );
-               #else
-                       return parse_error( words );
-               #endif
+       else if (words[0][0] == '!') {
+               system( original_request + 1 );
+               ret_val = 1;
        }
+       
+       free( original_request );
+       
+       if(!ret_val)
+               return parse_error( words );
+       else
+               return 1;
+}
 
-       return 1;
 
-}
+static int handle_introspect(char* words[]) {
 
+       if( ! words[1] )
+               return 0;
 
-int handle_introspect(char* words[]) {
+       fprintf(stderr, "--> %s\n", words[1]);
 
-       if(words[1] && words[2]) {
-               fprintf(stderr, "--> %s\n", words[1]);
-               char buf[256];
-               memset(buf,0,256);
-               sprintf( buf, "request %s opensrf.system.method %s", words[1], words[2] );
+       // Build a command in a suitably-sized
+       // buffer and then parse it
+       
+       size_t len;
+       if( words[2] ) {
+               static const char text[] = "request %s opensrf.system.method %s";
+               len = sizeof( text ) + strlen( words[1] ) + strlen( words[2] );
+               char buf[len];
+               sprintf( buf, text, words[1], words[2] );
                return parse_request( buf );
 
        } else {
-       
-               if(words[1]) {
-                       fprintf(stderr, "--> %s\n", words[1]);
-                       char buf[256];
-                       memset(buf,0,256);
-                       sprintf( buf, "request %s opensrf.system.method.all", words[1] );
-                       return parse_request( buf );
-               }
-       }
+               static const char text[] = "request %s opensrf.system.method.all";
+               len = sizeof( text ) + strlen( words[1] );
+               char buf[len];
+               sprintf( buf, text, words[1] );
+               return parse_request( buf );
 
-       return 0;
+       }
 }
 
 
-int handle_login( char* words[]) {
+static int handle_login( char* words[]) {
 
        if( words[1] && words[2]) {
 
@@ -317,7 +432,7 @@ int handle_login( char* words[]) {
        return 0;
 }
 
-int handle_set( char* words[]) {
+static int handle_set( char* words[]) {
 
        char* variable;
        if( (variable=words[1]) ) {
@@ -358,7 +473,7 @@ int handle_set( char* words[]) {
 }
 
 
-int handle_print( char* words[]) {
+static int handle_print( char* words[]) {
 
        char* variable;
        if( (variable=words[1]) ) {
@@ -381,7 +496,7 @@ int handle_print( char* words[]) {
        return 0;
 }
 
-int handle_router( char* words[] ) {
+static int handle_router( char* words[] ) {
 
        if(!client)
                return 1;
@@ -405,79 +520,8 @@ int handle_router( char* words[] ) {
 }
 
 
-/* if new shell, spawn a new child and subshell to do the work,
-       otherwise pipe the request to the currently open (piped) shell */
-int handle_exec(char* words[], int new_shell) {
-
-       if(!words[0]) return 0;
-
-       if( words[0] && words[0][0] == '!') {
-               int len = strlen(words[0]);
-               char command[len];
-               memset(command,0,len);
-       
-               int i; /* chop out the ! */
-               for( i=1; i!= len; i++) {
-                       command[i-1] = words[0][i];
-               }
-       
-               free(words[0]);
-               words[0] = strdup(command);
-       }
-
-       if(new_shell) {
-               signal(SIGCHLD, sig_child_handler);
 
-               if(fork()) {
-       
-                       waitpid(-1, 0, 0);
-                       if(child_dead) {
-                               signal(SIGCHLD,sig_child_handler);
-                               child_dead = 0;
-                       }
-       
-               } else {
-                       execvp( words[0], words );
-                       exit(0);
-               }
-
-       } else {
-
-
-               growing_buffer* b = buffer_init(64);
-               int i = 0;
-               while(words[i]) 
-                       buffer_fadd( b, "%s ", words[i++] );
-       
-               buffer_add( b, "\n");
-       
-               //int reader;
-               //int reader = dup2(STDOUT_FILENO, reader);
-               //int reader = dup(STDOUT_FILENO);
-               //close(STDOUT_FILENO);
-
-               fprintf( shell_writer, b->buf );
-               buffer_free(b);
-       
-               fflush(shell_writer);
-               usleep(1000);
-
-               /*
-               char c[4096];
-               bzero(c, 4096);
-               read( reader, c, 4095 );
-               fprintf(stderr, "read %s", c);
-               dup2(reader, STDOUT_FILENO);
-               */
-
-       }
-
-       
-       return 1;
-}
-
-
-int handle_request( char* words[], int relay ) {
+static int handle_request( char* words[], int relay ) {
 
        if(!client)
                return 1;
@@ -662,7 +706,7 @@ int send_request( char* server,
 }
 
 /*
-int handle_time( char* words[] ) {
+static int handle_time( char* words[] ) {
 
        if( ! words[1] ) {
 
@@ -688,7 +732,7 @@ int handle_time( char* words[] ) {
 
                
 
-int router_query_servers( char* router_server ) {
+static int router_query_servers( const char* router_server ) {
 
        if( ! router_server || strlen(router_server) == 0 ) 
                return 0;
@@ -724,8 +768,8 @@ int router_query_servers( char* router_server ) {
        
        return 1;
 }
-               
-int print_help() {
+
+static int print_help( void ) {
 
        printf(
                        "---------------------------------------------------------------------------------\n"
@@ -733,8 +777,10 @@ int print_help() {
                        "---------------------------------------------------------------------------------\n"
                        "help                   - Display this message\n"
                        "!<command> [args] - Forks and runs the given command in the shell\n"
-                       "time                   - Prints the current time\n"                                    
+               /*
+                       "time                   - Prints the current time\n"
                        "time <timestamp>       - Formats seconds since epoch into readable format\n"   
+               */
                        "set <variable> <value> - set a srfsh variable (e.g. set pretty_print true )\n"
                        "print <variable>               - Displays the value of a srfsh variable\n"
                        "---------------------------------------------------------------------------------\n"
@@ -778,8 +824,8 @@ int print_help() {
 }
 
 
-
-char* tabs(int count) {
+/*
+static char* tabs(int count) {
        growing_buffer* buf = buffer_init(24);
        int i;
        for(i=0;i!=count;i++)
@@ -789,15 +835,17 @@ char* tabs(int count) {
        buffer_free( buf );
        return final;
 }
+*/
+
 
-int handle_math( char* words[] ) {
+static int handle_math( char* words[] ) {
        if( words[1] )
                return do_math( atoi(words[1]), 0 );
        return 0;
 }
 
 
-int do_math( int count, int style ) {
+static int do_math( int count, int style ) {
 
        osrf_app_session* session = osrf_app_client_session_init(  "opensrf.math" );
        osrf_app_session_connect(session);
diff --git a/src/srfsh/srfsh.h b/src/srfsh/srfsh.h
deleted file mode 100644 (file)
index 6497231..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <opensrf/transport_client.h>
-#include <opensrf/osrf_message.h>
-#include <opensrf/osrf_app_session.h>
-#include <time.h>
-#include <sys/timeb.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <opensrf/utils.h>
-#include <opensrf/log.h>
-
-#include <signal.h>
-
-#include <stdio.h>
-#include <readline/readline.h>
-#include <readline/history.h>
-
-
-
-
-#define SRFSH_PORT 5222
-#define COMMAND_BUFSIZE 4096
-
-
-/* shell prompt */
-char* prompt = "srfsh# "; 
-
-char* history_file = NULL;
-
-int child_dead = 0;
-
-char* login_session = NULL;
-
-/* true if we're pretty printing json results */
-int pretty_print = 1;
-/* true if we're bypassing 'less' */
-int raw_print = 0;
-
-/* our jabber connection */
-transport_client* client = NULL; 
-
-/* the last result we received */
-osrf_message* last_result = NULL;
-
-/* functions */
-int parse_request( char* request );
-
-/* handles router requests */
-int handle_router( char* words[] );
-
-/* utility method for print time data */
-int handle_time( char* words[] );
-
-/* handles app level requests */
-int handle_request( char* words[], int relay );
-int handle_exec(char* words[], int new_shell);
-int handle_set( char* words[]);
-int handle_print( char* words[]);
-int send_request( char* server, 
-               char* method, growing_buffer* buffer, int relay );
-int parse_error( char* words[] );
-int router_query_servers( char* server );
-int srfsh_client_connect();
-int print_help();
-char* tabs(int count);
-void sig_child_handler( int s );
-void sig_int_handler( int s );
-
-int load_history();
-int handle_math( char* words[] );
-int do_math( int count, int style );
-int handle_introspect(char* words[]);
-int handle_login( char* words[]);