1 /*
2 * wsdlpull - A C++ parser for WSDL (Web services description language)
3 * Copyright (C) 2005-2007 Vivek Krishna
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 //An api to examine and invoke the web service in a protocol independent fashion
21
22 #ifndef _WSDLINVOKERH
23 #define _WSDLINVOKERH
24
25 #include "xmlpull/XmlSerializer.h"
26 #include "wsdlparser/WsdlParser.h"
27 #include "wsdlparser/Soap.h"
28 #include "xmlpull/wsdlpull_export.h"
29
30 #include "xmlpull/XmlDoc.h"
31
32 namespace WsdlPull{
33
34 struct Parameter
35 {
36 Parameter(Schema::Type ,std::string,int m,int x,const SchemaParser* s,
37 const std::vector<std::string>& parents);
38 Schema::Type type_;
39 std::string tag_;
40 unsigned int min_;
41 unsigned int max_;
42 int n_;
43 std::vector<std::string> data_;
44 //bool str_;
45 const SchemaParser* sParser_;
46 std::vector<std::string> parents_;
47
48 };
49
50 class WSDLPULL_EXPORT WsdlInvoker
51 {
52 public:
53 /** @name Constructors and Destructors */
54 //@{
55 /**
56 * The default constructor for WsdlInvoker
57 * @param wsdl url
58 * @param stream for logging errors
59 */
60
61 WsdlInvoker(const std::string &url, const std::string &schemaPath="");
62 WsdlInvoker(std::istream &input, const std::string &schemaPath = "");
63 WsdlInvoker();
64 ~WsdlInvoker();
65 //@}
66
67 /** @name WSDL Inspection*/
68 //@{
69 /** setWSDLUri
70 * set the url of the wsdl file to be processed
71 * @param url for the wsdl file
72 * @param optional path to schema files required to parse wsdl extensions (soap,http)
73 */
74 bool setWSDLUri(const std::string &url, const std::string & schemaPath="");
75 /** getOperations
76 * @param reference to vector<string>
77 * @brief return names of operations (only for the SOAP binding portType)
78 * @return int ,number of operations
79 */
80 int getOperations(std::vector<std::string> & operations);
81 std::string getOpDocumentation(const std::string & n);
82 std::string getDocumentation();
83 /** setOperation
84 * @param operation name to invoke
85 * @brief set the operation to invoke
86 * @return bool ,true if successful
87 */
88 bool setOperation(const std::string & operation,
89 WsdlPull::MessageType mType = WsdlPull::Input);
90 /** getServiceEndPoint
91 * returns the url to be invoked for the operation
92 */
93 std::string getServiceEndPoint(const std::string & opname) ;
94 //@}
95
96
97 /** @name Simple Invocation usage*/
98 //@{
99
100 /** setValue
101 * @brief sets the param value for an operation by name of the parameter
102 * @param name of the operation's parameter
103 * @param string/void* representation of the parameter
104 * @return true if successful,false if the values didnt match or occurrence constraint failed
105 * example invoker.setInputValue("symbol","ABC") or
106 * int zip = 94018; invoker.setInputValue("zip",(void*)(&zip));
107 * Note that "symbol" or "zip" above can be a message part or a constituent particle in a complex type
108 * The API takes care of it.
109 */
110 bool setValue(const std::string & param,void* val);
111 bool setValue(const std::string & param,void** values,unsigned int occur);
112 bool setValue(const std::string & param,std::string val);
113 bool setValue(const std::string & param,std::vector<std::string> values);//multiple occurrences
114 bool setValue(const std::vector<std::string> & parents,void* val);
115 /** invoke
116 * invoke the web service operation
117 @param timeout set the timeout for the request in seconds
118 * @return true if successful,false otherwise
119 */
120 bool invoke(long timeout = 0,bool processResponse = true);
121 /** getValue
122 * return the value of the output whose name is 'param'
123 * @param type is set by reference to enable type casting in client code
124 * @return pointer to the value or 0 if there is no simple type or part name
125 * whose name is 'param' in the web service output.
126 * example float * val = (int*) invoker.getOutput("Result",t);//stock quotes
127 * t would be Schema::FLOAT
128 */
129 void* getValue(const std::string & param,Schema::Type & t);
130
131
132 /** getValue
133 * return the value based on an xpath like expression
134 * @param xpath - the xpath expression or an element name which leads to a simple type element or attribute
135 * if it points to a simple type element,the element's text is returned, if it points to the attribute
136 * the attribute is returned
137 *
138 * /login/result/header/errorCode -> will do an absolute from the root node
139 * result/header/errorCode -> will do a relative match starting with "result"
140 * result//errorCode -> will return all "errorCode" under "result"
141 * //errorCode will return all "errorCode" from the root node
142 * result/@type -> will return attribute value of type for element result
143 * @param p_index - default value "1". Return the conten stored in the "Nth" node when several nodes that would match
144 * the xpath expression are found. It starts at "1" to comply with W3C Xpath standards
145 * A value of "0" would return the content of ll matching nodes, but this function does only
146 * return one "content"
147 * @return - The value , an empty string is returned if the xpath expression doesnt lead to some CDATA
148 * Exception is thrown if this method is called when the status() returns false or web service response is
149 * empty
150 * example float getValue<float>('StockQuoteResponse/quote')
151 */
152 template <typename T>
153 T getValue(const std::string & xpath, size_t p_index = 1);
154
155 /* identical to previous method but returns multiple matches if found in the document*/
156 template <typename T>
157 std::vector<T> getValues(const std::string & xpath);
158 //@}
159
160 /** @name A more complex but powerful usage*/
161 //@{
162
163 /** getNextInput
164 * Calling this method repeatedly informs the caller
165 * of the input types the web service operation expects.
166 * Each call returns a unique id which must be used while setting the
167 * value using setInputValue.This method exposes only atomic types.Even if
168 * a web service needs a complex type,the api exposes only the constituent
169 * particles.The only exception is when a complex content model needs multiple
170 * occurrences which is still a TODO
171 * @param ref:param name Name of the param
172 * @param ref:Schema::Type ,the schema type
173 * @param ref: minimum and maximum (occurrences)
174 * @param ref:parents, parent list of type hierarchy for this parameter.
175 * @return unique id of this parameter
176 */
177 int getNextInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum);
178 int getNextInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum,
179 std::vector<std::string>& parents);
180 /**
181 * getNextHeaderInput
182 * Similar to the previous method except that it gets the SOAP headers if any
183 * Set methods are same as for regular inputs
184 */
185 int getNextHeaderInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum);
186 int getNextHeaderInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum,
187 std::vector<std::string>& parents);
188 /**
189 * returns the number of input headers you may need to set
190 */
191 int nInputHeaders()const;
192
193 /** setInputValue
194 * sets the param value for an operation
195 * only simple types can be set.
196 * @param id return by getNextInput()
197 * @param void ** pointer to array of pointers to the the values
198 * @return true if successful,false if the values didnt match or occurrence constraint failed
199 */
200 bool setInputValue(const int param,void* val);
201 bool setInputValue(const int id,void** values,unsigned int occur);
202
203 /** setInputValue
204 * sets the param value for an operation
205 * only simple types can be set.
206 * @param id return by getNextInput()
207 * @param string representation of the parameter
208 * @return true if successful,false if the values didnt match or occurrence constraint failed
209 */
210 bool setInputValue(const int param,std::string val);
211 bool setInputValue(const int param,std::vector<std::string> values);//multiple occurrences
212
213 /** getNextOutput
214 * get the part/elem name and type container
215 * @return false when we finished iterating through all outputs
216 * after which it rewinds and you can start again
217 */
218 bool getNextOutput(std::string & name,TypeContainer * & tc);
219
220 /** getOutput
221 * return the type container which stores the output
222 * for the output part/elem name
223 */
224 TypeContainer* getOutput(const std::string & name);
225
226 /** getNextHeaderOutput
227 * get the type container which stores the SOAP header
228 * @return false when we finished iterating through all outputs
229 * after which it rewinds and you can start again
230 */
231 bool getNextHeaderOutput(std::string & name,TypeContainer*& tc);
232
233 //@}
234 // change location of the service
235 void setLocation(const std::string & url);
236 // set credentials for the service
237 void setCredentials(const std::string & user, const std::string & pass);
238 // set http authentication for the service
239 void setAuth(const std::string & user, const std::string & pass);
240 //ouput the soap message without invoking the service
241 std::string getSoapMessage();
242 std::string getXMLResponse();
243 void setProxy(const std::string & host,int port=80);
244 //enable logging
245 void setVerbose(bool f);
246 // prints the output along with typenames like
247 // name:value.
248 //if false only value is printed
249 void printTypeNames(bool f);
250 //get the error message
251 std::string errors();
252 //if this returns false something went wrong
253 bool status()const;
254
255 //get SOAP fault related things
256 std::string getFaultCode() const;
257 std::string getFaultSubCode() const;
258 std::string getFaultString() const;
259 std::string getFaultActor() const;
260
261 // Control XML Tree Generation and Xpath search fine tuning
262 void setProcessEnvAndBody( bool p_processEnvAndBody);
263 bool getProcessEnvAndBody( void) const;
264
265 void setLazyRelativeMatch( bool p_lazyRelativeMatch);
266 bool getLazyRelativeMatch( void) const;
267
268 void setBuildXmlTree( bool p_buildXmlTree);
269 bool getBuildXmlTree( void) const;
270 void buildXmlTree( XmlPullParser &p_xmlPullParser, XmlNode_t &p_xmlNode,
271 bool p_notScannedEventAvail = false);
272
273 private:
274 //private stuff
275
276 bool init(WsdlParser* parser);
277 //creaate xml request
278 void serialize();
279 void serializeType(Schema::Type typeId,
280 const std::string &tag,
281 const SchemaParser * sParser,
282 int minimum,
283 int maximum,
284 std::vector<std::string> parents,
285 const std::string nsp="",
286 bool isRoot = false);
287
288 void serializeParam(int n,const std::string & tag,
289 const SchemaParser * sParser,
290 const std::string nsp="",
291 bool isRoot = false);
292 void serializeContentModel(ContentModel *cm,
293 const SchemaParser *sParser,
294 std::vector<std::string> parents);
295 /** create xml request
296 and do the http post request
297 @param timeout in seconds default 0 -> no timeout
298 **/
299 void post(long timeout=0, std::string username="", std::string passwd="");
300 void processResults();
301 void processFault(XmlPullParser* xpp);
302 void processHeader(XmlPullParser *xpp);
303 void processBody(const Message* m,XmlPullParser* xpp);
304 void parseWsdl(const std::string & url, const std::string & schemaPath = "");
305 void serializeHeader();
306 bool isSoapArray (const ComplexType * ct,const SchemaParser * sParser);
307 //reset state information
308 void reset();
309 void getOperationDetails(const Operation* op);
310 std::string getPrefix(const std::string& nsp);
311 std::string getAsStringFromXPath(const std::string & xpath, size_t p_index, std::vector<std::string>* arr = 0);
312 bool isSubTreeNil();
313 WsdlParser * wParser_;
314 std::string strResults_;
315 WsdlParser * ourParser_;
316 XmlSerializer * xmlStream_;
317 Soap* soap_;
318 bool soapheaders_;
319 int hPartId_;
320 std::string hnsp_;
321 std::ostringstream * soapstr_;
322 std::ostringstream logger_;
323 bool status_;
324 bool serializeMode_;
325 bool verbose_;
326 bool dontPost_;
327 int oHeaders_;
328 std::map<std::string,const Operation*> opMap_;
329 const Operation* op_;
330 Soap::Encoding use_;//literal or encoded
331 std::string encodingStyle_; // this is usually the soap encoding style
332 Soap::Style style_;//rpc or doc
333 std::string nsp_; // namespace for the operation
334 std::string location_;
335 std::string username_,password_,host_;
336 int port_;
337 std::string action_;//SOAPAction header
338 std::vector<Parameter> elems_;//the simple types
339 size_t n_;//a counter to iterate through the element params
340 int iHeaders_; //number of soap header inputs
341 std::vector<std::pair<std::string,TypeContainer*> > outputs_;
342 std::vector<const XSDType* > avoidrecurse_;
343 WsdlPull::MessageType messageType_;
344
345 std::vector<std::string> prefixes_;
346 bool bAuth;
347 std::string sAuthUser;
348 std::string sAuthPass;
349
350 std::string sFaultCode;
351 std::string sFaultSubCode;
352 std::string sFaultString;
353 std::string sFaultActor;
354 void* ctx;//for connection purposes
355
356 bool m_buildXmlTree;
357 bool m_xmlTreeProduced;
358 XmlDoc_t m_xmlDoc;
359 };
360
361 inline
Parameter(Schema::Type t,std::string n,int m,int x,const SchemaParser * s,const std::vector<std::string> & parents)362 Parameter::Parameter(Schema::Type t,std::string n,int m,int x,const SchemaParser* s,
363 const std::vector<std::string>& parents)
364 :type_(t),
365 tag_(n),
366 min_(m),
367 max_(x),
368 n_(0),
369 sParser_(s),
370 parents_(parents)
371
372 {
373 }
374
375 inline
376 std::string
errors()377 WsdlInvoker::errors()
378 {
379 return logger_.str();
380 }
381
382 inline
383 bool
setWSDLUri(const std::string & url,const std::string & schemaPath)384 WsdlInvoker::setWSDLUri(const std::string &url,const std::string & schemaPath)
385 {
386 parseWsdl(url,schemaPath);
387 return status_;
388 }
389
390 inline
391 bool
status()392 WsdlInvoker::status()const
393 {
394 return status_;
395 }
396
397 inline
398 void
setLocation(const std::string & url)399 WsdlInvoker::setLocation(const std::string & url)
400 {
401 location_ = url;
402 }
403
404 inline
405 void
setVerbose(bool f)406 WsdlInvoker::setVerbose(bool f)
407 {
408 verbose_ = f;
409 }
410
411 inline
412 int
nInputHeaders()413 WsdlInvoker::nInputHeaders()const
414 {
415 return iHeaders_;
416 }
417
418 inline
419 std::string
getFaultCode()420 WsdlInvoker::getFaultCode() const
421 {
422 return sFaultCode;
423 }
424
425 inline
426 std::string
getFaultSubCode()427 WsdlInvoker::getFaultSubCode() const
428 {
429 return sFaultSubCode;
430 }
431
432 inline
433 std::string
getFaultString()434 WsdlInvoker::getFaultString() const
435 {
436 return sFaultString;
437 }
438
439 inline
440 std::string
getFaultActor()441 WsdlInvoker::getFaultActor() const
442 {
443 return sFaultActor;
444 }
445
446
447 template<typename T>
448 inline T
getValue(const std::string & xpath,size_t p_index)449 WsdlInvoker::getValue(const std::string & xpath, size_t p_index)
450 {
451
452 T val;
453 std::string v = getAsStringFromXPath(xpath, p_index);
454 std::istringstream iss(v);
455 iss>>val;
456 return val;
457 }
458
459 template<>
460 inline std::string
461 WsdlInvoker::getValue<std::string>(const std::string & xpath, size_t p_index)
462 {
463
464 return getAsStringFromXPath(xpath, p_index);
465
466 }
467
468 template <typename T>
469 inline std::vector<T>
getValues(const std::string & xpath)470 WsdlInvoker::getValues(const std::string & xpath)
471 {
472 std::vector<std::string> arr ;
473 std::vector<T> arrT;
474 getAsStringFromXPath(xpath, 0, &arr);
475 T val;
476 for (size_t s = 0 ;s<arr.size();s++){
477
478
479 std::istringstream iss(arr[s]);
480 iss>>val;
481 arrT.push_back(val);
482 }
483 return arrT;
484 }
485
486 //specialization for string
487 template<>
488 inline
489 std::vector<std::string>
490 WsdlInvoker::getValues<std::string>(const std::string & xpath)
491 {
492 std::vector<std::string> arr ;
493 getAsStringFromXPath(xpath, 0, &arr);
494 return arr;
495 }
496
497
498 }
499 #endif
500