# pxmlrpc.h

Go to the documentation of this file.

    00001 /*
    00002  * pxmlrpc.h
    00003  *
    00004  * XML/RPC support
    00005  *
    00006  * Portable Windows Library
    00007  *
    00008  * Copyright (c) 2002 Equivalence Pty. Ltd.
    00009  *
    00010  * The contents of this file are subject to the Mozilla Public License
    00011  * Version 1.0 (the "License"); you may not use this file except in
    00012  * compliance with the License. You may obtain a copy of the License at
    00013  * http://www.mozilla.org/MPL/
    00014  *
    00015  * Software distributed under the License is distributed on an "AS IS"
    00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
    00017  * the License for the specific language governing rights and limitations
    00018  * under the License.
    00019  *
    00020  * The Original Code is Portable Windows Library.
    00021  *
    00022  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
    00023  *
    00024  * Contributor(s): ______________________________________.
    00025  *
    00026  * $Revision: 23711 $
    00027  * $Author: rjongbloed $
    00028  * $Date: 2009-10-28 03:45:13 -0500 (Wed, 28 Oct 2009) $
    00029  */
    00030
    00031 #ifndef PTLIB_PXMLRPC_H
    00032 #define PTLIB_PXMLRPC_H
    00033
    00034 #ifdef P_USE_PRAGMA
    00035 #pragma interface
    00036 #endif
    00037
    00038 #include <ptclib/pxml.h>
    00039
    00040 #if P_XMLRPC
    00041
    00042 #include <ptclib/url.h>
    00043
    00044
    00045 class PXMLRPCBlock;
    00046 class PXMLRPCVariableBase;
    00047 class PXMLRPCStructBase;
    00048
    00049
    00051
    00052 class PXMLRPC : public PObject
    00053 {
    00054   PCLASSINFO(PXMLRPC, PObject);
    00055   public:
    00056     enum {
    00057       CannotCreateRequestXML          = 100,
    00058       CannotParseResponseXML,
    00059       CannotParseRequestXML,
    00060       HTTPPostFailed,
    00061       CannotReadResponseContentBody,
    00062       ResponseRootNotMethodResponse,
    00063       ResponseEmpty,
    00064       ResponseUnknownFormat,
    00065       ParamNotValue,
    00066       ScalarWithoutElement,
    00067       ParamNotStruct,
    00068       MemberIncomplete,
    00069       MemberUnnamed,
    00070       FaultyFault,
    00071       RequestHasWrongDocumentType,
    00072       RequestHasNoMethodName,
    00073       RequestHasNoParms,
    00074       MethodNameIsEmpty,
    00075       UnknownMethod,
    00076       ParamNotArray,
    00077
    00078       UserFault                       = 1000,
    00079     };
    00080
    00081     PXMLRPC(
    00082       const PURL & url,
    00083       PXML::Options options = PXML::NoOptions
    00084     );
    00085
    00086     void SetTimeout(const PTimeInterval & t) { timeout = t; }
    00087
    00088     PBoolean MakeRequest(const PString & method);
    00089     PBoolean MakeRequest(const PString & method,  PXMLRPCBlock & response);
    00090     PBoolean MakeRequest(PXMLRPCBlock & request, PXMLRPCBlock & response);
    00091     PBoolean MakeRequest(const PString & method, const PXMLRPCStructBase & args, PXMLRPCStructBase & reply);
    00092
    00093     PString GetFaultText() const { return faultText; }
    00094     PINDEX  GetFaultCode() const { return faultCode; }
    00095
    00096     static PBoolean    ISO8601ToPTime(const PString & iso8601, PTime & val, int tz = PTime::GMT);
    00097     static PString PTimeToISO8601(const PTime & val);
    00098
    00099   protected:
    00100     PBoolean PerformRequest(PXMLRPCBlock & request, PXMLRPCBlock & response);
    00101
    00102     PURL          url;
    00103     PINDEX        faultCode;
    00104     PString       faultText;
    00105     PTimeInterval timeout;
    00106     PXML::Options m_options;
    00107 };
    00108
    00110
    00111 class PXMLRPCBlock : public PXML
    00112 {
    00113   PCLASSINFO(PXMLRPCBlock, PXML);
    00114   public:
    00115     PXMLRPCBlock();
    00116     PXMLRPCBlock(const PString & method);
    00117     PXMLRPCBlock(const PString & method, const PXMLRPCStructBase & structData);
    00118
    00119     PBoolean Load(const PString & str);
    00120
    00121     PXMLElement * GetParams();
    00122     PXMLElement * GetParam(PINDEX idx) const;
    00123     PINDEX GetParamCount() const;
    00124
    00125     // used when used as a response
    00126     PINDEX  GetFaultCode() const                     { return faultCode; }
    00127     PString GetFaultText() const                     { return faultText; }
    00128     void SetFault(PINDEX code, const PString & text) { faultCode = code; faultText = text; }
    00129     PBoolean ValidateResponse();
    00130
    00131     // helper functions for getting parameters
    00132     PBoolean GetParams(PXMLRPCStructBase & data);
    00133     PBoolean GetParam(PINDEX idx, PString & type, PString & result);
    00134     PBoolean GetExpectedParam(PINDEX idx, const PString & expectedType, PString & value);
    00135
    00136     PBoolean GetParam(PINDEX idx, PString & result);
    00137     PBoolean GetParam(PINDEX idx, int & result);
    00138     PBoolean GetParam(PINDEX idx, double & result);
    00139     PBoolean GetParam(PINDEX idx, PTime & result, int tz = PTime::GMT);
    00140     PBoolean GetParam(PINDEX idx, PStringToString & result);
    00141     PBoolean GetParam(PINDEX idx, PXMLRPCStructBase & result);
    00142     PBoolean GetParam(PINDEX idx, PStringArray & result);
    00143     PBoolean GetParam(PINDEX idx, PArray<PStringToString> & result);
    00144
    00145     // static functions for parsing values
    00146     PBoolean ParseScalar(PXMLElement * element, PString & type, PString & value);
    00147     PBoolean ParseStruct(PXMLElement * element, PStringToString & structDict);
    00148     PBoolean ParseStruct(PXMLElement * element, PXMLRPCStructBase & structData);
    00149     PBoolean ParseArray(PXMLElement * element, PStringArray & array);
    00150     PBoolean ParseArray(PXMLElement * element, PArray<PStringToString> & array);
    00151     PBoolean ParseArray(PXMLElement * element, PXMLRPCVariableBase & array);
    00152
    00153     // static functions for creating values
    00154     static PXMLElement * CreateValueElement(PXMLElement * element);
    00155     static PXMLElement * CreateScalar(const PString & type, const PString & scalar);
    00156     static PXMLElement * CreateMember(const PString & name, PXMLElement * value);
    00157
    00158     static PXMLElement * CreateScalar(const PString & str);
    00159     static PXMLElement * CreateScalar(int value);
    00160     static PXMLElement * CreateScalar(double value);
    00161     static PXMLElement * CreateDateAndTime(const PTime & time);
    00162     static PXMLElement * CreateBinary(const PBYTEArray & data);
    00163
    00164     static PXMLElement * CreateStruct();
    00165     static PXMLElement * CreateStruct(const PStringToString & dict);
    00166     static PXMLElement * CreateStruct(const PStringToString & dict, const PString & typeStr);
    00167     static PXMLElement * CreateStruct(const PXMLRPCStructBase & structData);
    00168
    00169     static PXMLElement * CreateArray(const PStringArray & array);
    00170     static PXMLElement * CreateArray(const PStringArray & array, const PString & typeStr);
    00171     static PXMLElement * CreateArray(const PStringArray & array, const PStringArray & types);
    00172     static PXMLElement * CreateArray(const PArray<PStringToString> & array);
    00173     static PXMLElement * CreateArray(const PXMLRPCVariableBase & array);
    00174
    00175     // helper functions for adding parameters
    00176     void AddParam(PXMLElement * parm);
    00177     void AddParam(const PString & str);
    00178     void AddParam(int value);
    00179     void AddParam(double value);
    00180     void AddParam(const PTime & time);
    00181     void AddParam(const PXMLRPCStructBase & structData);
    00182     void AddBinary(const PBYTEArray & data);
    00183     void AddStruct(const PStringToString & dict);
    00184     void AddStruct(const PStringToString & dict, const PString & typeStr);
    00185     void AddArray(const PStringArray & array);
    00186     void AddArray(const PStringArray & array, const PString & typeStr);
    00187     void AddArray(const PStringArray & array, const PStringArray & types);
    00188     void AddArray(const PArray<PStringToString> & array);
    00189
    00190   protected:
    00191     PXMLElement * params;
    00192     PString faultText;
    00193     PINDEX  faultCode;
    00194 };
    00195
    00196
    00198
    00199 class PXMLRPCVariableBase : public PObject {
    00200     PCLASSINFO(PXMLRPCVariableBase, PObject);
    00201   protected:
    00202     PXMLRPCVariableBase(const char * name, const char * type = NULL);
    00203
    00204   public:
    00205     const char * GetName() const { return name; }
    00206     const char * GetType() const { return type; }
    00207
    00208     virtual void Copy(const PXMLRPCVariableBase & other) = 0;
    00209     virtual PString ToString(PINDEX i) const;
    00210     virtual void FromString(PINDEX i, const PString & str);
    00211     virtual PXMLRPCStructBase * GetStruct(PINDEX i) const;
    00212     virtual PBoolean IsArray() const;
    00213     virtual PINDEX GetSize() const;
    00214     virtual PBoolean SetSize(PINDEX);
    00215
    00216     PString ToBase64(PAbstractArray & data) const;
    00217     void FromBase64(const PString & str, PAbstractArray & data);
    00218
    00219   protected:
    00220     const char * name;
    00221     const char * type;
    00222
    00223   private:
    00224     PXMLRPCVariableBase(const PXMLRPCVariableBase &) : PObject() { }
    00225 };
    00226
    00227
    00228 class PXMLRPCArrayBase : public PXMLRPCVariableBase {
    00229     PCLASSINFO(PXMLRPCArrayBase, PXMLRPCVariableBase);
    00230   protected:
    00231     PXMLRPCArrayBase(PContainer & array, const char * name, const char * type);
    00232     PXMLRPCArrayBase & operator=(const PXMLRPCArrayBase &);
    00233
    00234   public:
    00235     virtual void PrintOn(ostream & strm) const;
    00236     virtual void Copy(const PXMLRPCVariableBase & other);
    00237     virtual PBoolean IsArray() const;
    00238     virtual PINDEX GetSize() const;
    00239     virtual PBoolean SetSize(PINDEX);
    00240
    00241   protected:
    00242     PContainer & array;
    00243 };
    00244
    00245
    00246 class PXMLRPCArrayObjectsBase : public PXMLRPCArrayBase {
    00247     PCLASSINFO(PXMLRPCArrayObjectsBase, PXMLRPCArrayBase);
    00248   protected:
    00249     PXMLRPCArrayObjectsBase(PArrayObjects & array, const char * name, const char * type);
    00250     PXMLRPCArrayObjectsBase & operator=(const PXMLRPCArrayObjectsBase &);
    00251
    00252   public:
    00253     virtual PString ToString(PINDEX i) const;
    00254     virtual void FromString(PINDEX i, const PString & str);
    00255     virtual PBoolean SetSize(PINDEX);
    00256
    00257     virtual PObject * CreateObject() const = 0;
    00258
    00259   protected:
    00260     PArrayObjects & array;
    00261 };
    00262
    00263
    00264 class PXMLRPCStructBase : public PObject {
    00265     PCLASSINFO(PXMLRPCStructBase, PObject);
    00266   protected:
    00267     PXMLRPCStructBase();
    00268     PXMLRPCStructBase & operator=(const PXMLRPCStructBase &);
    00269   private:
    00270     PXMLRPCStructBase(const PXMLRPCStructBase &) : PObject() { }
    00271
    00272   public:
    00273     void PrintOn(ostream & strm) const;
    00274
    00275     PINDEX GetNumVariables() const { return variablesByOrder.GetSize(); }
    00276     PXMLRPCVariableBase & GetVariable(PINDEX idx) const { return variablesByOrder[idx]; }
    00277     PXMLRPCVariableBase * GetVariable(const char * name) const { return variablesByName.GetAt(name); }
    00278
    00279     void AddVariable(PXMLRPCVariableBase * var);
    00280     static PXMLRPCStructBase & GetInitialiser() { return *PAssertNULL(initialiserInstance); }
    00281
    00282   protected:
    00283     void EndConstructor();
    00284
    00285     PArray<PXMLRPCVariableBase>               variablesByOrder;
    00286     PDictionary<PString, PXMLRPCVariableBase> variablesByName;
    00287
    00288     PXMLRPCStructBase        * initialiserStack;
    00289     static PMutex              initialiserMutex;
    00290     static PXMLRPCStructBase * initialiserInstance;
    00291 };
    00292
    00293
    00294 #define PXMLRPC_STRUCT_BEGIN(name) \
    00295   class name : public PXMLRPCStructBase { \
    00296     public: name() { EndConstructor(); } \
    00297     public: name(const name & other) { EndConstructor(); operator=(other); } \
    00298     public: name & operator=(const name & other) { PXMLRPCStructBase::operator=(other); return *this; }
    00299
    00300 #define PXMLRPC_VARIABLE_CLASS(base, type, variable, xmltype, init, extras) \
    00301     private: struct PXMLRPCVar_##variable : public PXMLRPCVariableBase { \
    00302       PXMLRPCVar_##variable() \
    00303         : PXMLRPCVariableBase(#variable, xmltype), \
    00304           instance(((base &)base::GetInitialiser()).variable) \
    00305         { init } \
    00306       virtual void PrintOn (ostream & s) const { s << instance; } \
    00307       virtual void ReadFrom(istream & s)       { s >> instance; } \
    00308       virtual void Copy(const PXMLRPCVariableBase & other) \
    00309                     { instance = ((PXMLRPCVar_##variable &)other).instance; } \
    00310       extras \
    00311       type & instance; \
    00312     } pxmlrpcvar_##variable
    00313
    00314 #define PXMLRPC_VARIABLE_CUSTOM(base, type, variable, xmltype, init, extras) \
    00315     public: type variable; \
    00316     PXMLRPC_VARIABLE_CLASS(base, type, variable, xmltype, init, extras)
    00317
    00318 #define PXMLRPC_ARRAY_CUSTOM(base, arraytype, basetype, variable, xmltype, par, extras) \
    00319     public: arraytype variable; \
    00320     private: struct PXMLRPCVar_##variable : public par { \
    00321       PXMLRPCVar_##variable() \
    00322         : par(((base &)base::GetInitialiser()).variable, #variable, xmltype), \
    00323           instance((arraytype &)array) \
    00324         { } \
    00325       extras \
    00326       arraytype & instance; \
    00327     } pxmlrpcvar_##variable
    00328 #ifdef DOCPLUSPLUS
    00329 }
    00330 #endif
    00331
    00332
    00333 #define PXMLRPC_STRUCT_END() \
    00334   };
    00335
    00336
    00337 #define PXMLRPC_VARIABLE(base, type, variable, xmltype) \
    00338         PXMLRPC_VARIABLE_CUSTOM(base, type, variable, xmltype, ;, ;)
    00339
    00340
    00341 #define PXMLRPC_VARIABLE_INIT(base, type, variable, xmltype, init) \
    00342         PXMLRPC_VARIABLE_CUSTOM(base, type, variable, xmltype, instance=init;, ;)
    00343
    00344
    00345 #define PXMLRPC_STRING(base, type, variable) \
    00346         PXMLRPC_VARIABLE(base, type, variable, "string")
    00347
    00348
    00349 #define PXMLRPC_STRING_INIT(base, type, variable, init) \
    00350         PXMLRPC_VARIABLE_INIT(base, type, variable, "string", init)
    00351
    00352
    00353 #define PXMLRPC_INTEGER(base, type, variable) \
    00354         PXMLRPC_VARIABLE(base, type, variable, "int")
    00355
    00356
    00357 #define PXMLRPC_INTEGER_INIT(base, type, variable, init) \
    00358         PXMLRPC_VARIABLE_INIT(base, type, variable, "int", init)
    00359
    00360
    00361 #define PXMLRPC_BOOLEAN(base, type, variable) \
    00362         PXMLRPC_VARIABLE(base, type, variable, "boolean")
    00363
    00364
    00365 #define PXMLRPC_BOOLEAN_INIT(base, type, variable, init) \
    00366         PXMLRPC_VARIABLE_INIT(base, type, variable, "boolean", init)
    00367
    00368
    00369 #define PXMLRPC_DOUBLE(base, type, variable) \
    00370         PXMLRPC_VARIABLE(base, type, variable, "double")
    00371
    00372
    00373 #define PXMLRPC_DOUBLE_INIT(base, type, variable, init) \
    00374         PXMLRPC_VARIABLE_INIT(base, type, variable, "double", init)
    00375
    00376
    00377 #define PXMLRPC_DATETIME(base, type, variable) \
    00378         PXMLRPC_VARIABLE_CUSTOM(base, type, variable, "dateTime.iso8601", ;, \
    00379                     PString ToString(PINDEX) const { return instance.AsString(PTime::ShortISO8601); } )
    00380
    00381
    00382 #define PXMLRPC_BINARY(base, type, variable) \
    00383         PXMLRPC_VARIABLE_CUSTOM(base, type, variable, "base64", ;, \
    00384                     PString ToString(PINDEX) const { return ToBase64(instance); } \
    00385                     void FromString(PINDEX, const PString & str) { FromBase64(str, instance); } )
    00386
    00387
    00388 #define PXMLRPC_STRUCT(base, type, variable) \
    00389         PXMLRPC_VARIABLE_CUSTOM(base, type, variable, "struct", ;, \
    00390                     PXMLRPCStructBase * GetStruct(PINDEX) const { return &instance; } )
    00391
    00392
    00393 #define PXMLRPC_ARRAY(base, arraytype, basetype, variable, xmltype) \
    00394         PXMLRPC_ARRAY_CUSTOM(base, arraytype, basetype, variable, xmltype, PXMLRPCArrayObjectsBase, \
    00395                     PObject * CreateObject() const { return new basetype; })
    00396
    00397
    00398 #define PXMLRPC_ARRAY_STRING(base, arraytype, basetype, variable) \
    00399         PXMLRPC_ARRAY(base, arraytype, basetype, variable, "string")
    00400
    00401 #define PXMLRPC_ARRAY_INTEGER(base, type, variable) \
    00402         PXMLRPC_ARRAY_CUSTOM(base, PScalarArray<type>, type, variable, "int", PXMLRPCArrayBase, \
    00403                     PString ToString(PINDEX i) const { return PString(instance[i]); } \
    00404                     void FromString(PINDEX i, const PString & str) { instance[i] = (type)str.AsInteger(); })
    00405
    00406 #define PXMLRPC_ARRAY_DOUBLE(base, type, variable) \
    00407         PXMLRPC_ARRAY_CUSTOM(base, PScalarArray<type>, type, variable, "double", PXMLRPCArrayBase, \
    00408                     PString ToString(PINDEX i) const { return psprintf("%f", instance[i]); } \
    00409                     void FromString(PINDEX i, const PString & str) { instance[i] = (type)str.AsReal(); })
    00410
    00411 #define PXMLRPC_ARRAY_STRUCT(base, type, variable) \
    00412         PXMLRPC_ARRAY_CUSTOM(base, PArray<type>, type, variable, "struct", PXMLRPCArrayObjectsBase, \
    00413                              PXMLRPCStructBase * GetStruct(PINDEX i) const { return &instance[i]; } \
    00414                              PObject * CreateObject() const { return new type; })
    00415
    00416
    00417 #define PXMLRPC_FUNC_NOARG_NOREPLY(name) \
    00418   PBoolean name() { return MakeRequest(#name); }
    00419
    00420
    00421 #define PXMLRPC_FUNC_SINGLE_ARG(name, vartype, argtype) \
    00422   class name##_in : public PXMLRPCStructBase { \
    00423     public: name##_in(const argtype & var) : variable(var) { EndConstructor(); } \
    00424         vartype(name##_in, argtype, variable);
    00425
    00426
    00427 #define PXMLRPC_FUNC_MULTI_ARGS(name) \
    00428   PXMLRPC_STRUCT_BEGIN(name##_in)
    00429
    00430
    00431 #ifdef DOCPLUSPLUS
    00432 {
    00433 #endif
    00434 #define PXMLRPC_FUNC_MULTI_REPLY(name) \
    00435   }; PXMLRPC_STRUCT_BEGIN(name##_out)
    00436
    00437
    00438 #ifdef DOCPLUSPLUS
    00439 {
    00440 #endif
    00441 #define PXMLRPC_FUNC_NO_ARGS(name) \
    00442   }; \
    00443   PBoolean name(name##_out & reply) \
    00444     { return MakeRequest(#name, name##_in(), reply); }
    00445
    00446
    00447 #ifdef DOCPLUSPLUS
    00448 {
    00449 #endif
    00450 #define PXMLRPC_FUNC_STRUCT_ARG(name) \
    00451   }; \
    00452   class name##_in_carrier : public PXMLRPCStructBase { \
    00453     public: name##_in_carrier(const name##_in & var) : variable(var) { EndConstructor(); } \
    00454     private: struct var_class : public PXMLRPCVariableBase { \
    00455       var_class(const name##_in & var) \
    00456         : PXMLRPCVariableBase("variable", "struct"), instance(var) { } \
    00457       virtual void PrintOn (ostream & s) const { s << instance; } \
    00458       virtual PXMLRPCStructBase * GetStruct(PINDEX) const { return (PXMLRPCStructBase *)&instance; } \
    00459       virtual void Copy(const PXMLRPCVariableBase &) { } \
    00460       const name##_in & instance; \
    00461     } variable; \
    00462   }; \
    00463   PBoolean name(const name##_in & args, name##_out & reply) \
    00464     { return MakeRequest(#name, name##_in_carrier(args), reply); }
    00465
    00466
    00467 #ifdef DOCPLUSPLUS
    00468 {
    00469 #endif
    00470 #define PXMLRPC_FUNC_NORM_ARGS(name) \
    00471   }; \
    00472   PBoolean name(const name##_in & args, name##_out & reply) \
    00473     { return MakeRequest(#name, args, reply); }
    00474
    00475
    00476
    00478
    00479 #endif // P_XMLRPC
    00480
    00481 #endif // PTLIB_PXMLRPC_H
    00482
    00483
    00484 // End Of File ///////////////////////////////////////////////////////////////