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 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 unsigned options = 0
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 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
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
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
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
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
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