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

Generated on Mon Dec 10 11:18:57 2007 for PTLib by  doxygen 1.5.1