PTLib Version 2.12.9

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
pxmlrpc.h
Go to the documentation of this file.
1 /*
2 * pxmlrpc.h
3 *
4 * XML/RPC support
5 *
6 * Portable Windows Library
7 *
8 * Copyright (c) 2002 Equivalence Pty. Ltd.
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * The Original Code is Portable Windows Library.
21 *
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23 *
24 * Contributor(s): ______________________________________.
25 *
26 * $Revision: 28521 $
27 * $Author: rjongbloed $
28 * $Date: 2012-11-16 11:29:10 +1100 (Fri, 16 Nov 2012) $
29 */
30
31 #ifndef PTLIB_PXMLRPC_H
32 #define PTLIB_PXMLRPC_H
33
34 #ifdef P_USE_PRAGMA
35 #pragma interface
36 #endif
37
38 #include <ptclib/pxml.h>
39
40 #if P_XMLRPC
41
42 #include <ptclib/url.h>
43
44
45 class PXMLRPCBlock;
46 class PXMLRPCVariableBase;
47 class PXMLRPCStructBase;
48
49
51
52 class PXMLRPC : public PObject
53 {
54 PCLASSINFO(PXMLRPC, PObject);
55 public:
56 enum {
57 CannotCreateRequestXML = 100,
58 CannotParseResponseXML,
59 CannotParseRequestXML,
60 HTTPPostFailed,
61 CannotReadResponseContentBody,
62 ResponseRootNotMethodResponse,
63 ResponseEmpty,
64 ResponseUnknownFormat,
65 ParamNotValue,
66 ScalarWithoutElement,
67 ParamNotStruct,
68 MemberIncomplete,
69 MemberUnnamed,
70 FaultyFault,
71 RequestHasWrongDocumentType,
72 RequestHasNoMethodName,
73 RequestHasNoParms,
74 MethodNameIsEmpty,
75 UnknownMethod,
76 ParamNotArray,
77
78 UserFault = 1000,
79 };
80
81 PXMLRPC(
82 const PURL & url,
83 PXML::Options options = PXML::NoOptions
84 );
85
86 void SetTimeout(const PTimeInterval & t) { timeout = t; }
87
88 PBoolean MakeRequest(const PString & method);
89 PBoolean MakeRequest(const PString & method, PXMLRPCBlock & response);
90 PBoolean MakeRequest(PXMLRPCBlock & request, PXMLRPCBlock & response);
91 PBoolean MakeRequest(const PString & method, const PXMLRPCStructBase & args, PXMLRPCStructBase & reply);
92
93 PString GetFaultText() const { return faultText; }
94 PINDEX GetFaultCode() const { return faultCode; }
95
96 static PBoolean ISO8601ToPTime(const PString & iso8601, PTime & val, int tz = PTime::GMT);
97 static PString PTimeToISO8601(const PTime & val);
98
99 protected:
100 PBoolean PerformRequest(PXMLRPCBlock & request, PXMLRPCBlock & response);
101
102 PURL url;
103 PINDEX faultCode;
104 PString faultText;
105 PTimeInterval timeout;
106 PXML::Options m_options;
107 };
108
110
111 class PXMLRPCBlock : public PXML
112 {
113 PCLASSINFO(PXMLRPCBlock, PXML);
114 public:
115 PXMLRPCBlock();
116 PXMLRPCBlock(const PString & method);
117 PXMLRPCBlock(const PString & method, const PXMLRPCStructBase & structData);
118
119 PBoolean Load(const PString & str);
120
121 PXMLElement * GetParams();
122 PXMLElement * GetParam(PINDEX idx) const;
123 PINDEX GetParamCount() const;
124
125 // used when used as a response
126 PINDEX GetFaultCode() const { return faultCode; }
127 PString GetFaultText() const { return faultText; }
128 void SetFault(PINDEX code, const PString & text) { faultCode = code; faultText = text; }
129 PBoolean ValidateResponse();
130
131 // helper functions for getting parameters
132 PBoolean GetParams(PXMLRPCStructBase & data);
133 PBoolean GetParam(PINDEX idx, PString & type, PString & result);
134 PBoolean GetExpectedParam(PINDEX idx, const PString & expectedType, PString & value);
135
136 PBoolean GetParam(PINDEX idx, PString & result);
137 PBoolean GetParam(PINDEX idx, int & result);
138 PBoolean GetParam(PINDEX idx, double & result);
139 PBoolean GetParam(PINDEX idx, PTime & result, int tz = PTime::GMT);
140 PBoolean GetParam(PINDEX idx, PStringToString & result);
141 PBoolean GetParam(PINDEX idx, PXMLRPCStructBase & result);
142 PBoolean GetParam(PINDEX idx, PStringArray & result);
143 PBoolean GetParam(PINDEX idx, PArray<PStringToString> & result);
144
145 // static functions for parsing values
146 PBoolean ParseScalar(PXMLElement * element, PString & type, PString & value);
147 PBoolean ParseStruct(PXMLElement * element, PStringToString & structDict);
148 PBoolean ParseStruct(PXMLElement * element, PXMLRPCStructBase & structData);
149 PBoolean ParseArray(PXMLElement * element, PStringArray & array);
150 PBoolean ParseArray(PXMLElement * element, PArray<PStringToString> & array);
151 PBoolean ParseArray(PXMLElement * element, PXMLRPCVariableBase & array);
152
153 // static functions for creating values
154 static PXMLElement * CreateValueElement(PXMLElement * element);
155 static PXMLElement * CreateScalar(const PString & type, const PString & scalar);
156 static PXMLElement * CreateMember(const PString & name, PXMLElement * value);
157
158 static PXMLElement * CreateScalar(const PString & str);
159 static PXMLElement * CreateScalar(int value);
160 static PXMLElement * CreateScalar(double value);
161 static PXMLElement * CreateDateAndTime(const PTime & time);
162 static PXMLElement * CreateBinary(const PBYTEArray & data);
163
164 static PXMLElement * CreateStruct();
165 static PXMLElement * CreateStruct(const PStringToString & dict);
166 static PXMLElement * CreateStruct(const PStringToString & dict, const PString & typeStr);
167 static PXMLElement * CreateStruct(const PXMLRPCStructBase & structData);
168
169 static PXMLElement * CreateArray(const PStringArray & array);
170 static PXMLElement * CreateArray(const PStringArray & array, const PString & typeStr);
171 static PXMLElement * CreateArray(const PStringArray & array, const PStringArray & types);
172 static PXMLElement * CreateArray(const PArray<PStringToString> & array);
173 static PXMLElement * CreateArray(const PXMLRPCVariableBase & array);
174
175 // helper functions for adding parameters
176 void AddParam(PXMLElement * parm);
177 void AddParam(const PString & str);
178 void AddParam(int value);
179 void AddParam(double value);
180 void AddParam(const PTime & time);
181 void AddParam(const PXMLRPCStructBase & structData);
182 void AddBinary(const PBYTEArray & data);
183 void AddStruct(const PStringToString & dict);
184 void AddStruct(const PStringToString & dict, const PString & typeStr);
185 void AddArray(const PStringArray & array);
186 void AddArray(const PStringArray & array, const PString & typeStr);
187 void AddArray(const PStringArray & array, const PStringArray & types);
188 void AddArray(const PArray<PStringToString> & array);
189
190 protected:
191 PXMLElement * params;
192 PString faultText;
193 PINDEX faultCode;
194 };
195
196
198
199 class PXMLRPCVariableBase : public PObject {
200 PCLASSINFO(PXMLRPCVariableBase, PObject);
201 protected:
202 PXMLRPCVariableBase(const char * name, const char * type = NULL);
203
204 public:
205 const char * GetName() const { return name; }
206 const char * GetType() const { return type; }
207
208 virtual void Copy(const PXMLRPCVariableBase & other) = 0;
209 virtual PString ToString(PINDEX i) const;
210 virtual void FromString(PINDEX i, const PString & str);
211 virtual PXMLRPCStructBase * GetStruct(PINDEX i) const;
212 virtual PBoolean IsArray() const;
213 virtual PINDEX GetSize() const;
214 virtual PBoolean SetSize(PINDEX);
215
216 PString ToBase64(PAbstractArray & data) const;
217 void FromBase64(const PString & str, PAbstractArray & data);
218
219 protected:
220 const char * name;
221 const char * type;
222
223 private:
224 PXMLRPCVariableBase(const PXMLRPCVariableBase &) : PObject() { }
225 };
226
227
228 class PXMLRPCArrayBase : public PXMLRPCVariableBase {
229 PCLASSINFO(PXMLRPCArrayBase, PXMLRPCVariableBase);
230 protected:
231 PXMLRPCArrayBase(PContainer & array, const char * name, const char * type);
232 PXMLRPCArrayBase & operator=(const PXMLRPCArrayBase &);
233
234 public:
235 virtual void PrintOn(ostream & strm) const;
236 virtual void Copy(const PXMLRPCVariableBase & other);
237 virtual PBoolean IsArray() const;
238 virtual PINDEX GetSize() const;
239 virtual PBoolean SetSize(PINDEX);
240
241 protected:
242 PContainer & array;
243 };
244
245
246 class PXMLRPCArrayObjectsBase : public PXMLRPCArrayBase {
247 PCLASSINFO(PXMLRPCArrayObjectsBase, PXMLRPCArrayBase);
248 protected:
249 PXMLRPCArrayObjectsBase(PArrayObjects & array, const char * name, const char * type);
250 PXMLRPCArrayObjectsBase & operator=(const PXMLRPCArrayObjectsBase &);
251
252 public:
253 virtual PString ToString(PINDEX i) const;
254 virtual void FromString(PINDEX i, const PString & str);
255 virtual PBoolean SetSize(PINDEX);
256
257 virtual PObject * CreateObject() const = 0;
258
259 protected:
260 PArrayObjects & array;
261 };
262
263
264 class PXMLRPCStructBase : public PObject {
265 PCLASSINFO(PXMLRPCStructBase, PObject);
266 protected:
267 PXMLRPCStructBase();
268 PXMLRPCStructBase & operator=(const PXMLRPCStructBase &);
269 private:
270 PXMLRPCStructBase(const PXMLRPCStructBase &) : PObject() { }
271
272 public:
273 void PrintOn(ostream & strm) const;
274
275 PINDEX GetNumVariables() const { return variablesByOrder.GetSize(); }
276 PXMLRPCVariableBase & GetVariable(PINDEX idx) const { return variablesByOrder[idx]; }
277 PXMLRPCVariableBase * GetVariable(const char * name) const { return variablesByName.GetAt(name); }
278
279 void AddVariable(PXMLRPCVariableBase * var);
280 static PXMLRPCStructBase & GetInitialiser();
281
282 protected:
283 void EndConstructor();
284
285 PArray<PXMLRPCVariableBase> variablesByOrder;
286 PDictionary<PString, PXMLRPCVariableBase> variablesByName;
287
288 PXMLRPCStructBase * initialiserStack;
289 static PMutex initialiserMutex;
290 static PXMLRPCStructBase * initialiserInstance;
291 };
292
293
294 #define PXMLRPC_STRUCT_BEGIN(name) \
295 class name : public PXMLRPCStructBase { \
296 public: name() { EndConstructor(); } \
297 public: name(const name & other) { EndConstructor(); operator=(other); } \
298 public: name & operator=(const name & other) { PXMLRPCStructBase::operator=(other); return *this; }
299
300 #define PXMLRPC_VARIABLE_CLASS(base, type, variable, xmltype, init, extras) \
301 private: struct PXMLRPCVar_##variable : public PXMLRPCVariableBase { \
302 PXMLRPCVar_##variable() \
303 : PXMLRPCVariableBase(#variable, xmltype), \
304 instance(((base &)base::GetInitialiser()).variable) \
305 { init } \
306 virtual void PrintOn (ostream & s) const { s << instance; } \
307 virtual void ReadFrom(istream & s) { s >> instance; } \
308 virtual void Copy(const PXMLRPCVariableBase & other) \
309 { instance = ((PXMLRPCVar_##variable &)other).instance; } \
310 extras \
311 type & instance; \
312 } pxmlrpcvar_##variable
313
314 #define PXMLRPC_VARIABLE_CUSTOM(base, type, variable, xmltype, init, extras) \
315 public: type variable; \
316 PXMLRPC_VARIABLE_CLASS(base, type, variable, xmltype, init, extras)
317
318 #define PXMLRPC_ARRAY_CUSTOM(base, arraytype, basetype, variable, xmltype, par, extras) \
319 public: arraytype variable; \
320 private: struct PXMLRPCVar_##variable : public par { \
321 PXMLRPCVar_##variable() \
322 : par(((base &)base::GetInitialiser()).variable, #variable, xmltype), \
323 instance((arraytype &)array) \
324 { } \
325 extras \
326 arraytype & instance; \
327 } pxmlrpcvar_##variable
328 #ifdef DOCPLUSPLUS
329 }
330 #endif
331
332
333 #define PXMLRPC_STRUCT_END() \
334 };
335
336
337 #define PXMLRPC_VARIABLE(base, type, variable, xmltype) \
338 PXMLRPC_VARIABLE_CUSTOM(base, type, variable, xmltype, ;, ;)
339
340
341 #define PXMLRPC_VARIABLE_INIT(base, type, variable, xmltype, init) \
342 PXMLRPC_VARIABLE_CUSTOM(base, type, variable, xmltype, instance=init;, ;)
343
344
345 #define PXMLRPC_STRING(base, type, variable) \
346 PXMLRPC_VARIABLE(base, type, variable, "string")
347
348
349 #define PXMLRPC_STRING_INIT(base, type, variable, init) \
350 PXMLRPC_VARIABLE_INIT(base, type, variable, "string", init)
351
352
353 #define PXMLRPC_INTEGER(base, type, variable) \
354 PXMLRPC_VARIABLE(base, type, variable, "int")
355
356
357 #define PXMLRPC_INTEGER_INIT(base, type, variable, init) \
358 PXMLRPC_VARIABLE_INIT(base, type, variable, "int", init)
359
360
361 #define PXMLRPC_BOOLEAN(base, type, variable) \
362 PXMLRPC_VARIABLE(base, type, variable, "boolean")
363
364
365 #define PXMLRPC_BOOLEAN_INIT(base, type, variable, init) \
366 PXMLRPC_VARIABLE_INIT(base, type, variable, "boolean", init)
367
368
369 #define PXMLRPC_DOUBLE(base, type, variable) \
370 PXMLRPC_VARIABLE(base, type, variable, "double")
371
372
373 #define PXMLRPC_DOUBLE_INIT(base, type, variable, init) \
374 PXMLRPC_VARIABLE_INIT(base, type, variable, "double", init)
375
376
377 #define PXMLRPC_DATETIME(base, type, variable) \
378 PXMLRPC_VARIABLE_CUSTOM(base, type, variable, "dateTime.iso8601", ;, \
379 PString ToString(PINDEX) const { return instance.AsString(PTime::ShortISO8601); } )
380
381
382 #define PXMLRPC_BINARY(base, type, variable) \
383 PXMLRPC_VARIABLE_CUSTOM(base, type, variable, "base64", ;, \
384 PString ToString(PINDEX) const { return ToBase64(instance); } \
385 void FromString(PINDEX, const PString & str) { FromBase64(str, instance); } )
386
387
388 #define PXMLRPC_STRUCT(base, type, variable) \
389 PXMLRPC_VARIABLE_CUSTOM(base, type, variable, "struct", ;, \
390 PXMLRPCStructBase * GetStruct(PINDEX) const { return &instance; } )
391
392
393 #define PXMLRPC_ARRAY(base, arraytype, basetype, variable, xmltype) \
394 PXMLRPC_ARRAY_CUSTOM(base, arraytype, basetype, variable, xmltype, PXMLRPCArrayObjectsBase, \
395 PObject * CreateObject() const { return new basetype; })
396
397
398 #define PXMLRPC_ARRAY_STRING(base, arraytype, basetype, variable) \
399 PXMLRPC_ARRAY(base, arraytype, basetype, variable, "string")
400
401 #define PXMLRPC_ARRAY_INTEGER(base, type, variable) \
402 PXMLRPC_ARRAY_CUSTOM(base, PScalarArray<type>, type, variable, "int", PXMLRPCArrayBase, \
403 PString ToString(PINDEX i) const { return PString(instance[i]); } \
404 void FromString(PINDEX i, const PString & str) { instance[i] = (type)str.AsInteger(); })
405
406 #define PXMLRPC_ARRAY_DOUBLE(base, type, variable) \
407 PXMLRPC_ARRAY_CUSTOM(base, PScalarArray<type>, type, variable, "double", PXMLRPCArrayBase, \
408 PString ToString(PINDEX i) const { return psprintf("%f", instance[i]); } \
409 void FromString(PINDEX i, const PString & str) { instance[i] = (type)str.AsReal(); })
410
411 #define PXMLRPC_ARRAY_STRUCT(base, type, variable) \
412 PXMLRPC_ARRAY_CUSTOM(base, PArray<type>, type, variable, "struct", PXMLRPCArrayObjectsBase, \
413 PXMLRPCStructBase * GetStruct(PINDEX i) const { return &instance[i]; } \
414 PObject * CreateObject() const { return new type; })
415
416
417 #define PXMLRPC_FUNC_NOARG_NOREPLY(name) \
418 PBoolean name() { return MakeRequest(#name); }
419
420
421 #define PXMLRPC_FUNC_SINGLE_ARG(name, vartype, argtype) \
422 class name##_in : public PXMLRPCStructBase { \
423 public: name##_in(const argtype & var) : variable(var) { EndConstructor(); } \
424 vartype(name##_in, argtype, variable);
425
426
427 #define PXMLRPC_FUNC_MULTI_ARGS(name) \
428 PXMLRPC_STRUCT_BEGIN(name##_in)
429
430
431 #ifdef DOCPLUSPLUS
432 {
433 #endif
434 #define PXMLRPC_FUNC_MULTI_REPLY(name) \
435 }; PXMLRPC_STRUCT_BEGIN(name##_out)
436
437
438 #ifdef DOCPLUSPLUS
439 {
440 #endif
441 #define PXMLRPC_FUNC_NO_ARGS(name) \
442 }; \
443 PBoolean name(name##_out & reply) \
444 { return MakeRequest(#name, name##_in(), reply); }
445
446
447 #ifdef DOCPLUSPLUS
448 {
449 #endif
450 #define PXMLRPC_FUNC_STRUCT_ARG(name) \
451 }; \
452 class name##_in_carrier : public PXMLRPCStructBase { \
453 public: name##_in_carrier(const name##_in & var) : variable(var) { EndConstructor(); } \
454 private: struct var_class : public PXMLRPCVariableBase { \
455 var_class(const name##_in & var) \
456 : PXMLRPCVariableBase("variable", "struct"), instance(var) { } \
457 virtual void PrintOn (ostream & s) const { s << instance; } \
458 virtual PXMLRPCStructBase * GetStruct(PINDEX) const { return (PXMLRPCStructBase *)&instance; } \
459 virtual void Copy(const PXMLRPCVariableBase &) { } \
460 const name##_in & instance; \
461 } variable; \
462 }; \
463 PBoolean name(const name##_in & args, name##_out & reply) \
464 { return MakeRequest(#name, name##_in_carrier(args), reply); }
465
466
467 #ifdef DOCPLUSPLUS
468 {
469 #endif
470 #define PXMLRPC_FUNC_NORM_ARGS(name) \
471 }; \
472 PBoolean name(const name##_in & args, name##_out & reply) \
473 { return MakeRequest(#name, args, reply); }
474
475
476
478
479 #endif // P_XMLRPC
480
481 #endif // PTLIB_PXMLRPC_H
482
483
484 // End Of File ///////////////////////////////////////////////////////////////