00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
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
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
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
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