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: 20385 $
00027  * $Author: rjongbloed $
00028  * $Date: 2008-06-04 10:40:38 +0000 (Wed, 04 Jun 2008) $
00029  */
00030 
00031 #ifndef _PXMLRPC_H
00032 #define _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       unsigned options = 0
00084     );
00085 
00086     void SetTimeout(const PTimeInterval & _timeout) { timeout = _timeout; }
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     unsigned      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 &) { }
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 &) { }
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 // _PXMLRPC_H

Generated on Mon Feb 23 01:57:54 2009 for PTLib by  doxygen 1.5.1