diff options
author | Andy Cedilnik <andy.cedilnik@kitware.com> | 2005-02-22 18:08:27 (GMT) |
---|---|---|
committer | Andy Cedilnik <andy.cedilnik@kitware.com> | 2005-02-22 18:08:27 (GMT) |
commit | b9b4ea0f7bbf0313d8aa5e354ee56f912969763c (patch) | |
tree | ba5e857cda91949be14f508e6df490e1e2176f40 /Utilities/cmxmlrpc/XmlRpcCpp.h | |
parent | bfcb4b693763bb11f841094d2ca9852a64e5d33b (diff) | |
download | CMake-b9b4ea0f7bbf0313d8aa5e354ee56f912969763c.zip CMake-b9b4ea0f7bbf0313d8aa5e354ee56f912969763c.tar.gz CMake-b9b4ea0f7bbf0313d8aa5e354ee56f912969763c.tar.bz2 |
ENH: Initial import
Diffstat (limited to 'Utilities/cmxmlrpc/XmlRpcCpp.h')
-rw-r--r-- | Utilities/cmxmlrpc/XmlRpcCpp.h | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/Utilities/cmxmlrpc/XmlRpcCpp.h b/Utilities/cmxmlrpc/XmlRpcCpp.h new file mode 100644 index 0000000..05a3ad0 --- /dev/null +++ b/Utilities/cmxmlrpc/XmlRpcCpp.h @@ -0,0 +1,428 @@ +// -*- C++ -*- <-- an Emacs control + +// Copyright information is at the bottom of the file. + +//========================================================================= +// XML-RPC C++ API +//========================================================================= + + +#ifndef _XMLRPCCPP_H_ +#define _XMLRPCCPP_H_ 1 + +// The C++ standard says we should either include <string.h> (which gets +// us the wrong header), or say 'using namespace std;' (which doesn't +// work with our version of g++). So this header name is technically wrong. +// Tell me what your compiler does; I can provide some autoconf magic to the +// Right Thing on most platforms. +// +// 2004.12.22 Bryan: This looks like a problem with whatever g++ he was +// using, so if anything, the special case should be for that. In any case, +// we've already added using namespace std to other files, without knowing +// there was an issue, so I'm just going to do the "using namespace" +// unconditionally and see who complains. If there are complaints, we can +// improve the documentation here. +// +// Formerly, the "using namespace std" was under +// "#if defined(__GNUC__) && (__GNUC__ >= 3)". + + +#include <string> + +using namespace std; + +#include <xmlrpc_config.h> +#include <xmlrpc.h> +#include <xmlrpc_client.h> +#include <xmlrpc_server.h> + +#define XMLRPC_NO_ASSIGNMENT \ + XMLRPC_FATAL_ERROR("Assignment operator not available"); return *this; + + +//========================================================================= +// XmlRpcFault +//========================================================================= +// A C++ exception class representing an XML-RPC fault. + +class XmlRpcFault { + +private: + xmlrpc_env mFault; + + XmlRpcFault& operator= (const XmlRpcFault& f) + { (void) f; XMLRPC_NO_ASSIGNMENT } + +public: + XmlRpcFault (const XmlRpcFault &fault); + XmlRpcFault (const int faultCode, const string faultString); + XmlRpcFault (const xmlrpc_env *env); + ~XmlRpcFault (void); + + int getFaultCode (void) const; + string getFaultString (void) const; + xmlrpc_env *getFaultEnv (void); +}; + +inline int XmlRpcFault::getFaultCode (void) const { + return mFault.fault_code; +} + +inline xmlrpc_env *XmlRpcFault::getFaultEnv (void) { + return &mFault; +} + + +//========================================================================= +// XmlRpcEnv +//========================================================================= +// This class can be used to wrap xmlrpc_env object. Use it as follows: +// +// XmlRpcEnv env; +// xmlrpc_parse_value(env, v, "(i)", &i); +// env.throwIfFaultOccurred(); + +class XmlRpcEnv { + +private: + xmlrpc_env mEnv; + + void throwMe (void) const; + XmlRpcEnv& operator= (const XmlRpcEnv& e) + { (void) e; XMLRPC_NO_ASSIGNMENT } + +public: + XmlRpcEnv (const XmlRpcEnv &env); + XmlRpcEnv (void) { xmlrpc_env_init(&mEnv); } + ~XmlRpcEnv (void) { xmlrpc_env_clean(&mEnv); } + + bool faultOccurred (void) const { return mEnv.fault_occurred; }; + bool hasFaultOccurred (void) const { return faultOccurred(); }; + /* hasFaultOccurred() is for backward compatibility. + faultOccurred() is a superior name for this. + */ + XmlRpcFault getFault (void) const; + + void throwIfFaultOccurred (void) const; + + operator xmlrpc_env * (void) { return &mEnv; } +}; + +inline void XmlRpcEnv::throwIfFaultOccurred (void) const { + if (faultOccurred()) + throwMe(); +} + + +//========================================================================= +// XmlRpcValue +//========================================================================= +// An object in this class is an XML-RPC value. +// +// We have a complex structure to allow C code mixed in with C++ code +// which uses this class to refer to the same XML-RPC value object. +// This is especially important because there aren't proper C++ facilities +// for much of Xmlrpc-c; you have to use the C facilities even if you'd +// rather use proper C++. +// +// The XmlRpcValue object internally represents the value as an +// xmlrpc_value. It hold one reference to the xmlrpc_value. Users +// of XmlRpcValue never see that xmlrpc_value, but C code can. the +// C code might create the xmlrpc_value and then bind it to an XmlRpcValue, +// or it might get the xmlrpc_value handle from the XmlRpcValue. Finally, +// C code can simply use the XmlRpcValue where an xmlrpc_value handle is +// required and it gets converted automatically. +// +// So reference counting for the xmlrpc_value is quite a nightmare. + +class XmlRpcValue { + +private: + xmlrpc_value *mValue; + +public: + enum ReferenceBehavior { + MAKE_REFERENCE, + CONSUME_REFERENCE + }; + + typedef xmlrpc_int32 int32; + + XmlRpcValue (void); + XmlRpcValue (xmlrpc_value *value, + ReferenceBehavior behavior = MAKE_REFERENCE); + XmlRpcValue (const XmlRpcValue& value); + ~XmlRpcValue (void); + + XmlRpcValue& operator= (const XmlRpcValue& value); + + // Accessing the value's type (think of this as lightweight RTTI). + xmlrpc_type getType(void) const; + + // We don't supply an automatic conversion operator--you need to say + // whether you want to make or borrow this object's reference. + // XXX - Is it really OK for these to be const? + xmlrpc_value *makeReference (void) const; + xmlrpc_value *borrowReference (void) const; + + // Some static "constructor" functions. + static XmlRpcValue makeInt (const XmlRpcValue::int32 i); + static XmlRpcValue makeBool (const bool b); + static XmlRpcValue makeDouble (const double d); + static XmlRpcValue makeDateTime (const string& dateTime); + static XmlRpcValue makeString (const string& str); + static XmlRpcValue makeString (const char *const str); + static XmlRpcValue makeString (const char *const str, size_t len); + static XmlRpcValue makeArray (void); + static XmlRpcValue makeStruct (void); + static XmlRpcValue makeBase64 (const unsigned char *const data, + size_t len); + /* + // An interface to xmlrpc_build_value. + static XmlRpcValue buildValue (const char *const format, ...); + */ + + // Some functions to get the underlying data. + // These will throw an XmlRpcFault if the data is the wrong type. + XmlRpcValue::int32 getInt (void) const; + bool getBool (void) const; + double getDouble (void) const; + string getRawDateTime (void) const; + string getString (void) const; + XmlRpcValue getArray (void) const; + XmlRpcValue getStruct (void) const; + + // This returns an internal pointer which will become invalid when + // all references to the underlying value are destroyed. + void getBase64 (const unsigned char *& out_data, + size_t& out_len) const; + + /* + // An interface to xmlrpc_parse_value. + void parseValue (const char *const format, ...); + */ + + // Array functions. These will throw an XmlRpcFault if the value + // isn't an array. + size_t arraySize (void) const; + void arrayAppendItem (const XmlRpcValue& value); + XmlRpcValue arrayGetItem (int index) const; + + // Struct functions. These will throw an XmlRpcFault if the value + // isn't a struct. + size_t structSize (void) const; + bool structHasKey (const string& key) const; + XmlRpcValue structGetValue (const string& key) const; + void structSetValue (const string& key, const XmlRpcValue& value); + void structGetKeyAndValue (const int index, + string& out_key, + XmlRpcValue& out_value) const; +}; + +inline XmlRpcValue::XmlRpcValue (xmlrpc_value *value, + ReferenceBehavior behavior) +{ + mValue = value; + + if (behavior == MAKE_REFERENCE) + xmlrpc_INCREF(value); +} + +inline XmlRpcValue::XmlRpcValue (const XmlRpcValue& value) { + mValue = value.mValue; + xmlrpc_INCREF(mValue); +} + +inline XmlRpcValue::~XmlRpcValue (void) { + xmlrpc_DECREF(mValue); +} + +inline XmlRpcValue& XmlRpcValue::operator= (const XmlRpcValue& value) { + // Must increment before we decrement, in case of assignment to self. + xmlrpc_INCREF(value.mValue); + xmlrpc_DECREF(mValue); + mValue = value.mValue; + return *this; +} + +inline xmlrpc_type XmlRpcValue::getType (void) const { + return xmlrpc_value_type(mValue); +} + +inline xmlrpc_value *XmlRpcValue::makeReference (void) const { + xmlrpc_INCREF(mValue); + return mValue; +} + +inline xmlrpc_value *XmlRpcValue::borrowReference (void) const { + return mValue; +} + + +//========================================================================= +// XmlRpcClient +//========================================================================= + +class XmlRpcClient { + +private: + string mServerUrl; + +public: + static void Initialize (string appname, string appversion); + static void Terminate (void); + + XmlRpcClient (const string& server_url) : mServerUrl(server_url) {} + ~XmlRpcClient (void) {} + + XmlRpcClient (const XmlRpcClient& client); + XmlRpcClient& operator= (const XmlRpcClient& client); + + XmlRpcValue call (string method_name, XmlRpcValue param_array); + void call_asynch (string method_name, + XmlRpcValue param_array, + xmlrpc_response_handler callback, + void* user_data); + void event_loop_asynch (unsigned long milliseconds); +}; + +inline void XmlRpcClient::call_asynch(string method_name, + XmlRpcValue param_array, + xmlrpc_response_handler callback, + void* user_data) +{ + xmlrpc_client_call_asynch_params( + mServerUrl.c_str(), + method_name.c_str(), + callback, + user_data, + param_array.borrowReference()); +} + +inline void XmlRpcClient::event_loop_asynch(unsigned long milliseconds) +{ + xmlrpc_client_event_loop_finish_asynch_timeout(milliseconds); +} + + +//========================================================================= +// XmlRpcClient Methods +//========================================================================= +// These are inline for now, so we don't need to screw with linker issues +// and build a separate client library. + +inline XmlRpcClient::XmlRpcClient (const XmlRpcClient& client) + : mServerUrl(client.mServerUrl) +{ +} + +inline XmlRpcClient& XmlRpcClient::operator= (const XmlRpcClient& client) { + if (this != &client) + mServerUrl = client.mServerUrl; + return *this; +} + +inline void XmlRpcClient::Initialize (string appname, string appversion) { + xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, + appname.c_str(), + appversion.c_str()); +} + +inline void XmlRpcClient::Terminate (void) { + xmlrpc_client_cleanup(); +} + +inline XmlRpcValue XmlRpcClient::call (string method_name, + XmlRpcValue param_array) +{ + XmlRpcEnv env; + xmlrpc_value *result = + xmlrpc_client_call_params(env, + mServerUrl.c_str(), + method_name.c_str(), + param_array.borrowReference()); + env.throwIfFaultOccurred(); + return XmlRpcValue(result, XmlRpcValue::CONSUME_REFERENCE); +} + +//========================================================================= +// XmlRpcGenSrv +//========================================================================= + +class XmlRpcGenSrv { + +private: + + xmlrpc_registry* mRegistry; + + xmlrpc_mem_block* alloc (XmlRpcEnv& env, const string& body) const; + +public: + + XmlRpcGenSrv (int flags); + ~XmlRpcGenSrv (void); + + xmlrpc_registry* getRegistry (void) const; + + XmlRpcGenSrv& addMethod (const string& name, + xmlrpc_method method, + void *data); + XmlRpcGenSrv& addMethod (const string& name, + xmlrpc_method method, + void* data, + const string& signature, + const string& help); + + string handle (const string& body) const; +}; + +inline XmlRpcGenSrv::XmlRpcGenSrv (int flags) { + + XmlRpcEnv env; + + if (flags == flags){}; + + mRegistry = xmlrpc_registry_new (env); + env.throwIfFaultOccurred(); +} + +inline XmlRpcGenSrv::~XmlRpcGenSrv (void) { + + xmlrpc_registry_free (mRegistry); +} + +inline xmlrpc_registry* XmlRpcGenSrv::getRegistry () const { + + return mRegistry; +} + +#undef XMLRPC_NO_ASSIGNMENT + + +// Copyright (C) 2001 by Eric Kidd. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. The name of the author may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. + + +#endif /* _XMLRPCCPP_H_ */ |