Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

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 * $Log: pxmlrpc.h,v $ 00027 * Revision 1.20 2004/05/17 06:05:20 csoutheren 00028 * Changed "make docs" to use doxygen 00029 * Added new config file and main page 00030 * 00031 * Revision 1.19 2003/04/15 07:08:36 robertj 00032 * Changed read and write from streams for base array classes so operates in 00033 * the same way for both PIntArray and PArray<int> etc 00034 * 00035 * Revision 1.18 2003/04/15 03:00:41 robertj 00036 * Added array support to XML/RPC 00037 * Fixed XML/RPC parsing when lots of white space in raw XML, caused by 00038 * big fix to base XML parser not returning internal data elements. 00039 * 00040 * Revision 1.17 2003/01/28 05:08:07 robertj 00041 * Fixed copy constructor on function arguments and return value 00042 * 00043 * Revision 1.16 2002/12/16 06:57:15 robertj 00044 * Added ability to specify certain elemets (by name) that are exempt from 00045 * the indent formatting. Useful for XML/RPC where leading white space is 00046 * not ignored by all servers. 00047 * Improved the macros for defining RPC functions. 00048 * 00049 * Revision 1.15 2002/12/13 01:04:56 robertj 00050 * Added copy constructor and assignment operator to XML/RPC structs 00051 * 00052 * Revision 1.14 2002/12/10 04:44:43 robertj 00053 * Added support in PTime for ISO 8601 format. 00054 * 00055 * Revision 1.13 2002/12/09 04:06:18 robertj 00056 * Added macros for defining multi-argument functions 00057 * 00058 * Revision 1.12 2002/12/04 02:09:26 robertj 00059 * Changed macro name prefix to PXMLRPC 00060 * 00061 * Revision 1.11 2002/12/04 00:31:13 robertj 00062 * Fixed GNU compatibility 00063 * 00064 * Revision 1.10 2002/12/04 00:15:56 robertj 00065 * Large enhancement to create automatically encoding and decoding structures 00066 * using macros to build a class. 00067 * 00068 * Revision 1.9 2002/11/06 22:47:24 robertj 00069 * Fixed header comment (copyright etc) 00070 * 00071 * Revision 1.8 2002/10/02 08:54:34 craigs 00072 * Added support for XMLRPC server 00073 * 00074 * Revision 1.7 2002/09/16 01:08:59 robertj 00075 * Added #define so can select if #pragma interface/implementation is used on 00076 * platform basis (eg MacOS) rather than compiler, thanks Robert Monaghan. 00077 * 00078 * Revision 1.6 2002/08/13 03:02:07 robertj 00079 * Removed previous fix for memory leak, as object was already deleted. 00080 * 00081 * Revision 1.5 2002/08/13 01:55:00 craigs 00082 * Fixed memory leak on PXMLRPCRequest class 00083 * 00084 * Revision 1.4 2002/08/06 01:04:03 robertj 00085 * Fixed missing pragma interface/implementation 00086 * 00087 * Revision 1.3 2002/07/12 05:51:14 craigs 00088 * Added structs to XMLRPC response types 00089 * 00090 * Revision 1.2 2002/03/27 00:50:44 craigs 00091 * Fixed problems with parsing faults and creating structs 00092 * 00093 * Revision 1.1 2002/03/26 07:06:50 craigs 00094 * Initial version 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 // used when used as a response 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 // helper functions for getting parameters 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 // static functions for parsing values 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 // static functions for creating values 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 // helper functions for adding parameters 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

Generated on Sat Jul 24 15:35:56 2004 for PWLib by doxygen 1.3.7