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