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