WsdlInvoker.cpp

Go to the documentation of this file.
00001 /* 
00002  * wsdlpull - A C++ parser  for WSDL  (Web services description language)
00003  * Copyright (C) 2005-2007 Vivek Krishna
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public
00016  * License along with this library; if not, write to the Free
00017  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018  */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023 #ifdef  WITH_CURL
00024 #include <curl/curl.h>
00025 #endif 
00026 
00027 #include <iostream>
00028 using namespace std;
00029 
00030 #include "wsdlparser/WsdlInvoker.h"
00031 
00032 
00033 
00034 #ifdef WITH_CURL
00035 size_t storeResults(void * buf, size_t sz, size_t nmemb, void* userdata);
00036 #endif
00037 
00038 namespace WsdlPull {
00039 
00040 WsdlInvoker::WsdlInvoker()
00041   :wParser_(0),
00042    ourParser_(0),
00043    xmlStream_(0),
00044    soap_(0),
00045    soapheaders_(false),
00046    hPartId_(-1),
00047    soapstr_(0),
00048    status_(false),
00049    serializeMode_(false),
00050    verbose_(false),
00051    dontPost_(false),
00052    oHeaders_(0),
00053    op_(0),
00054    n_(0),
00055    iHeaders_(0),
00056    messageType_(WsdlPull::Input),
00057    bAuth(false),
00058    ctx(0),
00059    m_buildXmlTree( false),
00060    m_xmlTreeProduced( false)
00061 {
00062 }
00063 
00064 WsdlInvoker::WsdlInvoker(std::istream &input, const std::string &schemaPath) 
00065   :wParser_(0),
00066    ourParser_(0),
00067    xmlStream_(0),
00068    soap_(0),
00069    soapheaders_(false),
00070    hPartId_(-1),
00071    soapstr_(0),
00072    status_(false),
00073    serializeMode_(false),
00074    verbose_(false),
00075    dontPost_(false),
00076    op_(0),
00077    n_(0),
00078    iHeaders_(0),
00079    messageType_(WsdlPull::Input),
00080    bAuth(false),
00081    ctx(0),
00082    m_buildXmlTree( false),
00083    m_xmlTreeProduced( false)
00084 {
00085   try{
00086     wParser_ = new WsdlParser(input,logger_, schemaPath);
00087     ourParser_= wParser_;
00088     if (wParser_){
00089       //parse the web service
00090       while (wParser_->getNextElement () != WsdlParser::END);
00091       if (wParser_->status()){
00092         
00093         status_=true;
00094         init(wParser_);
00095       }
00096     }
00097   }
00098   catch (WsdlException we)
00099   {
00100     logger_<<"An exception  occurred at "<<we.line   
00101     <<":"<<we.col<<std::endl;
00102     logger_<<we.description<<std::endl;
00103     status_ =false;
00104   }
00105   catch (SchemaParserException spe)
00106   {
00107     logger_<<"An exception occurred at "<<spe.line
00108     <<":"<<spe.col<<std::endl;
00109     logger_<<spe.description<<std::endl;
00110     status_ =false;
00111   }
00112   catch (XmlPullParserException xpe)
00113   {
00114     logger_<<"An exception occurred at "<<xpe.line
00115     <<":"<<xpe.col<<std::endl;
00116     logger_<<xpe.description<<std::endl;
00117     status_= false;
00118   }
00119 }
00120 
00121 WsdlInvoker::WsdlInvoker(const std::string & url, const std::string & schemaPath)
00122    :wParser_(0),
00123     ourParser_(0),
00124     xmlStream_(0),
00125     soap_(0),
00126     soapheaders_(false),
00127     hPartId_(-1),
00128     soapstr_(0),
00129     status_(false),
00130     serializeMode_(false),
00131     verbose_(false),
00132     dontPost_(false),
00133     op_(0),
00134     n_(0),
00135     iHeaders_(0),
00136     messageType_(WsdlPull::Input),
00137     bAuth(false),
00138     ctx(0),
00139     m_buildXmlTree( false),
00140     m_xmlTreeProduced( false)
00141 {
00142   parseWsdl(url, schemaPath);
00143 }
00144 
00145 
00146 void
00147 WsdlInvoker::parseWsdl(const std::string & url, const std::string & schemaPath)
00148 {
00149   try{
00150     wParser_ = new WsdlParser(url,logger_, schemaPath);
00151     ourParser_= wParser_;
00152     if (wParser_){
00153       //parse the web service
00154       while (wParser_->getNextElement () != WsdlParser::END);
00155       if (wParser_->status()){
00156       
00157         status_=true;
00158         init(wParser_);
00159       }
00160     }
00161   }
00162     catch (WsdlException we)
00163       {
00164        logger_<<"An exception  occurred at "<<we.line   
00165              <<":"<<we.col<<std::endl;
00166         logger_<<we.description<<std::endl;
00167         status_ =false;
00168       }
00169     catch (SchemaParserException spe)
00170       {
00171        logger_<<"An exception occurred at "<<spe.line
00172              <<":"<<spe.col<<std::endl;
00173         logger_<<spe.description<<std::endl;
00174         status_ =false;
00175       }
00176     catch (XmlPullParserException xpe)
00177       {
00178        logger_<<"An exception occurred at "<<xpe.line
00179              <<":"<<xpe.col<<std::endl;
00180        logger_<<xpe.description<<std::endl;
00181        status_= false;
00182       }
00183 }
00184 
00185 bool
00186 WsdlInvoker::init(WsdlParser* parser)
00187 {
00188   try{
00189     wParser_ = parser;
00190     status_ = wParser_->status();
00191 
00192     if (status_){
00193       
00194       PortType::cPortTypeIterator p1,p2;
00195       wParser_->getPortTypes(p1,p2);
00196       int i=0;
00197 
00198       while(p1!=p2){
00199     
00200         Operation::cOpIterator op1,op2;
00201         (*p1)->getOperations(op1,op2);
00202         bool bn = (*p1)->binding(Soap::soapBindingUri11) || (*p1)->binding(Soap::soapBindingUri12) ; 
00203         //if neither SOAP1.1 or SOAP1.2 bindings are available for a port type skip it
00205         if (!bn){
00206           p1++;
00207           continue;
00208         }
00209 
00210         while(op1!=op2){
00211         
00212           opMap_[(*op1)->getName()]=*op1;
00213           op1++; 
00214           i++;
00215         }
00216         p1++;
00217       }
00218     }
00219   }
00220   catch (WsdlException we)
00221     {
00222       logger_<<"A WSDL exception occurred at"<<we.line
00223              <<":"<<we.col<<std::endl;
00224       logger_<<we.description<<std::endl;
00225       status_ =false;
00226     }
00227   catch (SchemaParserException spe)
00228     {
00229       logger_<<"A Schema Parser exception occurred at "<<spe.line
00230              <<":"<<spe.col<<std::endl;
00231       logger_<<spe.description<<std::endl;
00232       status_ =false;
00233     }
00234   catch (XmlPullParserException xpe)
00235     {
00236       logger_<<"An Xml Parsing exception occurred at row:col "<<xpe.line
00237              <<":"<<xpe.col<<std::endl;
00238       logger_<<xpe.description<<std::endl;
00239       status_ =false;
00240     }
00241   return status_;
00242 }
00243  
00244 int
00245 WsdlInvoker::getOperations(std::vector<std::string> & operations)
00246 {
00247   int i = 0;
00248   for(
00249   std::map<std::string,const Operation*>::iterator it =
00250     opMap_.begin();
00251   it != opMap_.end();
00252   it++,i++){
00253 
00254     operations.push_back(it->first);
00255   }
00256   return i;
00257 }
00258 
00259 std::string
00260 WsdlInvoker::getDocumentation()
00261 {
00262   std::stringstream result;
00263   result << wParser_->getDocumentation();
00264   return result.str();
00265 }
00266    
00267 std::string
00268 WsdlInvoker::getOpDocumentation(const std::string & n)
00269 {
00270   
00271   std::map<std::string,const Operation*>::iterator it =
00272     opMap_.find(n);
00273   
00274   if (it != opMap_.end()){
00275     
00276     return  it->second->getDocumentation();
00277   }
00278   return "";
00279 }
00280 
00281 bool
00282 WsdlInvoker::setOperation(const std::string & opname,
00283                           WsdlPull::MessageType mType)
00284 {
00285   reset();
00286   messageType_ = mType;
00287    std::map<std::string,const Operation*>::iterator it =
00288     opMap_.find(opname);
00289 
00290   if (it != opMap_.end()){
00291     
00292     op_ = it->second;
00293 
00294     getOperationDetails(op_);
00295     if (!status_)
00296       return false;
00297     
00298     if (soapheaders_){
00299       serializeHeader();
00300     }
00301     serialize();
00302     n_ = iHeaders_;
00303     return status_;
00304   }
00305   else{
00306     return false;
00307   }
00308 }
00309 
00310 std::string
00311 WsdlInvoker::getServiceEndPoint(const std::string & opname) 
00312 {
00313 
00314   reset();
00315   location_="";
00316   std::map<std::string,const Operation*>::iterator it =
00317     opMap_.find(opname);
00318 
00319   if (it != opMap_.end()){
00320     
00321     const Operation* op = it->second;
00322 
00323     getOperationDetails(op);
00324     reset();
00325   }
00326   return location_;
00327 }
00328 
00329 void
00330 WsdlInvoker::getOperationDetails(const Operation* op) 
00331 {
00332 
00333   const Binding * bnSoap = 0;
00334   bnSoap = op->portType()->binding(Soap::soapBindingUri11);
00335   if (bnSoap) {
00336 
00337     soap_ = static_cast<Soap*> (wParser_->getExtensibilityHandler(Soap::soapBindingUri11));
00338   }else {
00339     
00340     bnSoap = op->portType()->binding(Soap::soapBindingUri12);
00341     soap_ = static_cast<Soap*> (wParser_->getExtensibilityHandler(Soap::soapBindingUri12));
00342 
00343   }
00344   
00346   soap_->getServiceLocation (bnSoap->getServiceExtId (),location_);
00347   style_ = soap_->getStyle();
00348 
00349   if (location_.empty()){
00350 
00351     logger_<<"No service location specified for SOAP binding "<<bnSoap->getName()<<std::endl;
00352     status_ = false;
00353     return;
00354   }
00355   //get the soap:operation's SOAPAction and style
00356   const int *bindings = 0;
00357   int opIndex  = bnSoap->getOperationIndex(op->getName());
00358   bnSoap->getOpBinding (opIndex, bindings);
00359   int soapOpBindingId = bindings[0];
00360   //operation's style over rides 
00361   soap_->getSoapOperationInfo (soapOpBindingId, action_, style_);
00362 
00363   //get the soap:body namespace and use attributes
00364   int nBindings=bnSoap->getInputBinding(opIndex,bindings);
00365   //get the body and header
00366   for (int x=0;x<nBindings;x++){
00367     if (soap_->isSoapBody(bindings[x])){
00368 
00369       soap_->getSoapBodyInfo(bindings[x],nsp_,use_,encodingStyle_);
00370     }
00371     if (soap_->isSoapHeader(bindings[x]))
00372       soapheaders_ = true;
00373 
00374   }
00375     
00376   if (nsp_.empty()){
00377 
00378     nsp_ = wParser_->getNamespace();
00379   }
00380 }
00381 
00382 void
00383 WsdlInvoker::serializeHeader()
00384 {
00385   //create input  holders for the soap header,use the same list
00386   //but just remember where the header's params end
00387   std::string name;
00388   
00389   int hPartId;
00390   const Message* hMessage;//message corresponding to soap header
00391 
00392   const Binding * bnSoap = op_->portType()->binding(soap_->getNamespace());
00393   const int *bindings = 0;
00394   int opIndex  = op_->portType()->getOperationIndex(op_->getName());
00395   int nBindings=bnSoap->getInputBinding(opIndex,bindings);
00396   //get the body and header
00397   for (int x=0;x<nBindings;x++){
00398     
00399     if (soap_->isSoapHeader(bindings[x])){
00400       
00401       soap_->getSoapHeaderInfo(bindings[x],hnsp_,hPartId,hMessage);  
00402 
00403   
00404       Schema::Type pType =Schema::XSD_INVALID;
00405       if (hMessage->getPartRefType(hPartId)==Part::Elem){
00406         
00407         name = hMessage->getMessagePart(hPartId)->element()->getName();
00408         pType = (Schema::Type)hMessage->getMessagePart(hPartId)->element()->getType();
00409       }
00410       else {
00411         
00412         name = hMessage->getPartName(hPartId);
00413         pType = (Schema::Type)hMessage->getMessagePart(hPartId)->type();
00414       }
00415       std::vector<std::string> parents;
00416       parents.push_back(name);
00417       serializeType(pType,
00418                     name,
00419                     wParser_->getSchemaParser(hMessage->getPartContentSchemaId(hPartId)),
00420                     1,1,parents,hnsp_,true);
00421     }
00422   }
00423   iHeaders_ = elems_.size();
00424 
00425 }
00426 
00427 //this method extracts the  atomic types needed for the web service
00428 //it recursively calls serializeType for all the input or output types expected
00429 //This method works in 2 modes.In the serializeMode_ == false it creates holders
00430 //for the parameter values.In serializeMode_ == true it uses the inputs from the holders 
00431 //to generate the SOAP XML message
00432 void
00433 WsdlInvoker::serialize()
00434 {
00435   const Message * m = op_->getMessage(messageType_);
00436   if (!m)
00437     return;
00438   
00439   for (int i = 0 ;i<m->getNumParts();i++){
00440       
00441     Part::PartRefType prt = m->getPartRefType(i);
00442     const Part * p = m->getMessagePart(i);
00443     const SchemaParser * sParser = wParser_->getSchemaParser(p->schemaId());
00444     const std::string nsp = sParser->getNamespace();
00445     
00446     std::vector<std::string> parents;
00447     if (prt == Part::Elem){
00448       
00449       const Element * e = p->element();
00450       serializeType((Schema::Type)e->getType(),e->getName(),sParser,1,1,parents,nsp,true);
00451     }
00452     else{
00453       
00454       serializeType((Schema::Type)p->type(),p->name(),sParser,1,1,parents,nsp,true);
00455     }
00456   }
00457 }
00458 
00459 void
00460 WsdlInvoker::serializeType(Schema::Type typeId,
00461                            const std::string &tag,
00462                            const SchemaParser * sParser,
00463                            int minimum,
00464                            int maximum,
00465                            std::vector<std::string> parents,
00466                            const std::string nsp,
00467                            bool isRoot)
00468 {
00469   std::string t = tag;
00470   if (t == "*")
00471     t = "item";
00472 
00473 
00474   //for( std::vector<std::string>::iterator it=parents.begin();it!=parents.end();it++) std::cout<<*it; 
00475 
00476   const XSDType * pType = sParser->getType(typeId);
00477 
00478   for (size_t z=0;z<avoidrecurse_.size();z++){
00479     //if there is a recursive type reference return to avoid infinite loop
00480     if (avoidrecurse_[z] == pType) 
00481       return;
00482     
00483   }
00484   avoidrecurse_.push_back(pType);
00485   
00486   if ( pType== 0 ||
00487        pType->isSimple() ||
00488        pType->getContentModel() == Schema::Simple){
00489     //simple types
00490     if (serializeMode_ == false){
00491       
00492       parents.push_back(tag);
00493       Parameter p(typeId,t,minimum,maximum,sParser,parents);
00494       elems_.push_back(p);
00495 
00496 #ifdef LOGGING
00497 
00498       std::cout<<"Adding input type "<<tag<<XmlUtils::dbsp
00499                <<sParser->getTypeName(typeId)<<XmlUtils::dbsp;
00500       std::cout<<sParser->getNamespace()<<std::endl;
00501 #endif
00502     }
00503     else{
00504       //generate the xml
00505       serializeParam(n_++,t,sParser,nsp,isRoot);
00506     }
00507   }
00508   else{
00509 
00510     if (serializeMode_){
00511       
00512       if (style_ == Soap::DOC ){
00513     
00514 
00515           if (sParser->getElementQualified()) {
00516             
00517             xmlStream_->startTag("",t);
00518             if (isRoot)
00519               xmlStream_->attribute("","xmlns",nsp);
00520           }
00521           else {
00522         
00523             if (isRoot) {
00524               xmlStream_->setPrefix(getPrefix(nsp),nsp);  
00525               xmlStream_->startTag(nsp,t);
00526             } 
00527             else {
00528               xmlStream_->startTag("",t);
00529             }
00530           }
00531         }
00532       
00533       else{
00534 
00535         xmlStream_->startTag("",t);
00536 
00537         //fix for sending SOAP arrays.add the soap arrayType attribute
00538         //works only for 1-D arrays
00539         const ComplexType* ct = static_cast<const ComplexType*>(pType);
00540         if(isSoapArray(ct,sParser)){
00541 
00542           std::string arrayName = ct->getName();
00543           arrayName = "ns:"+arrayName+"[1]";
00544           xmlStream_->attribute(soap_->getEncodingUri(),"arrayType",arrayName);
00545         }
00546       }
00547     }
00548     else {
00549       
00550       //complex types with multiple occurences
00551 
00552 
00553       //      parents.push_back(tag);
00554       //      Parameter p(typeId,t,minimum,maximum,sParser,parents);
00555       //      elems_.push_back(p);       TODO
00556       
00557     }
00558     
00559     
00560     const ComplexType * ct =
00561       static_cast<const ComplexType*>(pType);
00562     
00563     //complex types handling
00564     if (ct->getNumAttributes() > 0) {
00565       
00566       for (int i = 0; i < ct->getNumAttributes(); i++) {
00567           
00568         const Attribute*at = ct->getAttribute(i);
00569         /*
00570          * Check for the correctness of each attribute
00571          */
00572         if (at->isRequired()){
00573         
00574           if (serializeMode_ == false){
00575 
00576             std::vector<std::string> attparents(parents);
00577             attparents.push_back(tag);
00578             attparents.push_back("#" + at->getName() + "#");
00579             Parameter p((Schema::Type)at->getType(),at->getName(),elems_.size(),0,sParser,
00580                         attparents);
00581             elems_.push_back(p);
00582           }
00583           else{
00584             //generate the xml
00585             
00586             xmlStream_->attribute(sParser->getNamespace(),at->getName(),elems_[n_++].data_[0]);
00587           }
00588         }
00589         else
00590           continue;
00591       }
00592     }
00593   
00594     if (ct->getContentModel() == Schema::Simple) {
00595 
00596       if (serializeMode_ == false){
00597       
00598         parents.push_back(tag);
00599         Parameter p((Schema::Type)ct->getContentType(),tag,minimum,maximum,sParser,parents);
00600         elems_.push_back(p);
00601       }
00602       else{
00603         //generate the xml
00604         serializeParam(n_++,t,sParser,nsp,isRoot);
00605       }
00606     }
00607     else{
00608       
00609       const XSDType * baseType=sParser->getType(ct->getBaseTypeId());
00610       if (baseType && !baseType->isSimple()){
00611 
00612         const ComplexType * cType=static_cast<const ComplexType*>(baseType);
00613         ContentModel * bCm = cType->getContents();
00614         if (bCm){
00615           
00616           parents.push_back(tag);
00617           serializeContentModel(bCm,sParser,parents);
00618         }
00619       }
00620       ContentModel* cm=ct->getContents();
00621       if(cm){
00622 
00623         parents.push_back(tag);
00624         serializeContentModel(cm,sParser,parents);
00625       }
00626     }
00627 
00628     if (serializeMode_){
00629 
00630 
00631 
00632 
00633 
00634       if (style_ == Soap::DOC ){
00635     
00636         if (sParser->getElementQualified()) {
00637             
00638           xmlStream_->endTag("",t);
00639         }
00640         else {
00641           
00642           if (isRoot) {
00643             
00644             xmlStream_->endTag(nsp,t);
00645           } 
00646           else {
00647               xmlStream_->endTag("",t);
00648           }
00649         }
00650       }
00651       else{
00652         
00653         xmlStream_->endTag("",t);
00654 
00655 
00656       }
00657     }
00658   }
00659   avoidrecurse_.pop_back();
00660 }
00661 
00662 void
00663 WsdlInvoker::serializeContentModel(ContentModel *cm,
00664                                    const SchemaParser *sParser,
00665                                    std::vector<std::string> parents)
00666 {
00667   
00668   ContentModel::ContentsIterator cit_b=cm->begin();
00669   ContentModel::ContentsIterator cit_e=cm->end();
00670   ContentModel::ContentsIterator ci=cit_b;
00671 
00672         
00673   switch (cm->getCompositor())
00674     {
00675     case Schema::All:
00676     case Schema::Sequence:
00677     case Schema::Choice:
00678       {
00679         // a simple logic to start with
00680         // not taking care of all,choice ,sequence as of now
00681         
00682         for (ci=cit_b;ci!=cit_e;ci++){
00683           
00684           if(ci->second==ContentModel::Particle &&
00685              ci->first.e->getMax() > 0){
00686 
00687 
00688             const SchemaParser* s1Parser = sParser;
00689             bool isRoot = false;
00690             std::string nsp;
00691             Schema::Type t=(Schema::Type)ci->first.e->getType();
00692             
00693             if (!ci->first.e->getTypeNamespace().empty() &&
00694                 sParser->isImported(ci->first.e->getTypeNamespace()) &&
00695                 sParser->getNamespace() != ci->first.e->getTypeNamespace()) {
00696         
00697               //here the type of the element is defined in another imported schemaparser
00698               //so try to get the pointer.
00699               if ( !sParser->isBasicType(t)){ 
00700                   t = (Schema::Type)sParser->getType(t)->getTypeId();
00701                   sParser = sParser->getImportedSchemaParser(ci->first.e->getTypeNamespace());
00702               }
00703               if(ci->first.e->getNamespace() != s1Parser->getNamespace()){
00704                 nsp = ci->first.e->getNamespace();
00705                 isRoot = true ;// the element is from another namespace so need to qualify it
00706               }
00707                 
00708             }
00709            
00710             serializeType(t,
00711                           ci->first.e->getName(),
00712                           sParser,
00713                           ci->first.e->getMin(),
00714                           ci->first.e->getMax(),
00715                           parents,
00716                           nsp,isRoot);
00717             sParser = s1Parser;
00718           }
00719           else if (ci->second==ContentModel::Container) {
00720             
00721             //nested xsd:sequence inside choice..nested content models
00722             serializeContentModel(ci->first.c,
00723                                   sParser,
00724                                   parents);
00725               
00726           }
00727           else if (ci->second==ContentModel::ParticleGroup){
00728             
00729             //xsd:group inside 
00730             serializeContentModel(ci->first.g->getContents(),
00731                                   sParser,
00732                                   parents);
00733           }
00734         }
00735         break;
00736       }
00737     }
00738 }
00739 
00740 
00741 void
00742 WsdlInvoker::serializeParam(int n,const std::string & tag,
00743                             const SchemaParser * sParser,
00744                             const std::string nsp,
00745                             bool isRoot)
00746 {
00747 
00748   std::string t=tag;
00749   if (tag=="*")
00750     t="item";
00751     
00752   for (int i = 0 ;i<elems_[n].n_;i++){
00753 
00754     if (style_ == Soap::DOC){
00755 
00756       if (!isRoot)
00757         xmlStream_->startTag("",t);
00758       
00759       else {
00760         
00761         if (!nsp.empty())
00762           xmlStream_->setPrefix(getPrefix(nsp),nsp);
00763 
00764         xmlStream_->startTag(nsp,t);
00765 
00766       }
00767     }
00768     else{
00769       
00770         xmlStream_->startTag("",t);
00771         
00772         //xsi::type is needed for many SOAP servers
00773         if (sParser->isBasicType(elems_[n].type_) && 
00774             use_ == Soap::ENCODED){
00775           
00776           xmlStream_->attribute(Schema::SchemaInstaceUri,
00777                                 "type",
00778                                 "xsd:"+sParser->getTypeName(elems_[n].type_));
00779         }
00780     }
00781     
00782     xmlStream_->text(elems_[n].data_[i]);
00783     if (style_ == Soap::DOC && isRoot)
00784       xmlStream_->endTag(nsp,t);
00785     else
00786       xmlStream_->endTag("",t);
00787     
00788     
00789   }
00790 }
00791 
00792 
00793 bool
00794 WsdlInvoker::setInputValue(const int param,void** values,unsigned int occurs)
00795 {
00796 
00797   if (occurs < elems_[param].min_ ||
00798       occurs > elems_[param].max_)
00799     return false;
00800 
00801   SchemaValidator *sv = new SchemaValidator (elems_[param].sParser_);
00802   for (unsigned int i = 0 ;i < occurs ;i++){
00803       
00804     TypeContainer * tc = sv->validate(values[i],
00805                                       elems_[param].type_);
00806     if (!tc->isValueValid()){
00807         
00808       return false;
00809     }
00810     std::ostringstream oss;
00811     tc->print(oss);
00812     elems_[param].data_.push_back(oss.str());
00813     delete tc;
00814   }
00815   delete sv;
00816   
00817   elems_[param].n_ = occurs;
00818   return true;
00819 }
00820 
00821 bool
00822 WsdlInvoker::setInputValue(const int param,std::vector<std::string> values)
00823 {
00824 
00825 
00826   if (values.size() < elems_[param].min_ ||
00827       values.size() > elems_[param].max_)
00828     return false;
00829 
00830   SchemaValidator *sv = new SchemaValidator (elems_[param].sParser_);
00831   
00832   for (size_t i = 0 ;i < values.size() ;i++){
00833       
00834     TypeContainer * tc = sv->validate(values[i],
00835                                       elems_[param].type_);
00836     if (!tc->isValueValid()){
00837         
00838       return false;
00839     }
00840     elems_[param].data_.push_back(values[i]);
00841     delete tc;
00842   }
00843   delete sv;
00844   
00845   elems_[param].n_ = values.size();
00846   return true;
00847 }
00848 
00849 bool
00850 WsdlInvoker::setInputValue(const int param,std::string val)
00851 {
00852 
00853   const SchemaParser* sParser = elems_[param].sParser_;
00854   SchemaValidator *sv = new SchemaValidator (sParser);
00855   Schema::Type t = elems_[param].type_;
00856   const XSDType * pType = sParser->getType(t);
00857   if (pType && !pType->isSimple()){
00858 
00859     if (pType->getContentModel() != Schema::Simple)
00860       return false;
00861 
00862     const ComplexType * ct = static_cast<const ComplexType*>(pType);
00863     t = (Schema::Type)ct->getContentType();
00864   }
00865   
00866   TypeContainer * tc = sv->validate(val,t);
00867   if (!(tc && tc->isValueValid())){
00868         
00869     return false;
00870   }
00871   if (elems_[param].data_.size() == 0)
00872     elems_[param].data_.push_back(val);
00873   else
00874     elems_[param].data_[0]=val;
00875 
00876   delete tc;
00877     
00878   delete sv;
00879   
00880   elems_[param].n_ = 1;
00881   return true;
00882 }
00883 
00884 
00885 
00886 bool
00887 WsdlInvoker::setInputValue(const int param,void* val)
00888 {
00889 
00890   const SchemaParser*  sParser = elems_[param].sParser_;
00891   SchemaValidator *sv = new SchemaValidator (sParser);
00892   Schema::Type t = elems_[param].type_;
00893   const XSDType * pType = sParser->getType(t);
00894   if (pType && !pType->isSimple()){
00895 
00896     if (pType->getContentModel() != Schema::Simple)
00897       return false;
00898 
00899     const ComplexType * ct = static_cast<const ComplexType*>(pType);
00900     t = (Schema::Type)ct->getContentType();
00901   }
00902 
00903   TypeContainer * tc = sv->validate(val,t);
00904   if (!(tc && tc->isValueValid())){
00905         
00906     return false;
00907   }
00908   std::ostringstream oss;
00909   tc->print(oss);
00910   if (elems_[param].data_.size() == 0)
00911     elems_[param].data_.push_back(oss.str());
00912   else
00913     elems_[param].data_[0]=oss.str();
00914   delete tc;
00915   delete sv;
00916   elems_[param].n_ = 1;
00917   return true;
00918 }
00919 
00920 bool
00921 WsdlInvoker::setValue(const std::string & param,void* val)
00922 {
00923   for (size_t s = 0;s<elems_.size();s++){
00924     
00925     if (elems_[s].tag_ == param)
00926       return setInputValue(s,val);
00927   }
00928   return false;
00929 }
00930 
00931 bool
00932 WsdlInvoker::setValue(const std::string & param,void** values,unsigned int occur)
00933 {
00934 
00935   for (size_t s = 0;s<elems_.size();s++){
00936     
00937     if (elems_[s].tag_ == param)
00938       return setInputValue(s,values,occur);
00939   }
00940   return false;
00941 }
00942  
00943 bool
00944 WsdlInvoker::setValue(const std::string & param,std::string val)
00945 {
00946   for (size_t s = 0;s<elems_.size();s++){
00947     
00948     if (elems_[s].tag_ == param)
00949       return setInputValue(s,val);
00950   }
00951   return false;
00952 }
00953 
00954 bool
00955 WsdlInvoker::setValue(const std::string & param,std::vector<std::string> values)
00956 {
00957   for (size_t s = 0;s<elems_.size();s++){
00958     
00959     if (elems_[s].tag_ == param)
00960       return setInputValue(s,values);
00961   }
00962   return false;
00963 }
00964 
00965 
00966 std::string
00967 WsdlInvoker::getSoapMessage(){
00968 
00969   dontPost_ = true;
00970   invoke();
00971   dontPost_ = false;
00972   return soapstr_->str();
00973 }
00974 
00975 std::string
00976 WsdlInvoker::getXMLResponse(){
00977  
00978   return strResults_;
00979 }
00980 
00981 
00982 bool
00983 WsdlInvoker::invoke(long timeout,bool processResponse)
00984 {
00985 
00986 try{
00987     
00988   if (xmlStream_){
00989     
00990     delete xmlStream_;
00991   }
00992   if (soapstr_){
00993     
00994     delete soapstr_;
00995   }
00996   if (!strResults_.empty()){
00997     strResults_.clear();
00998   }
00999 
01000 
01001   for (size_t x = 0;x<outputs_.size();x++)
01002     delete outputs_[x].second;
01003 
01004   outputs_.clear();
01005 
01006   soapstr_ = new std::ostringstream();
01007   xmlStream_ = new XmlSerializer(*soapstr_);
01008 
01009   serializeMode_ = true;
01010 
01011   xmlStream_->startDocument("UTF-8",false);
01012   xmlStream_->setPrefix("SOAP-ENV",soap_->getEnvelopeUri());
01013   xmlStream_->setPrefix("SOAP-ENC",soap_->getEncodingUri());
01014   xmlStream_->setPrefix("xsd",Schema::SchemaUri);
01015   xmlStream_->setPrefix("xsi",Schema::SchemaInstaceUri);
01016   xmlStream_->setPrefix(getPrefix(nsp_),nsp_);
01017   xmlStream_->startTag(soap_->getEnvelopeUri(),"Envelope");
01018   
01019   if (style_ == Soap::RPC) {
01020     
01021     xmlStream_->attribute(soap_->getEnvelopeUri(),
01022                           "encodingStyle",
01023                           soap_->getEncodingUri());
01024   }
01025 
01026   n_ = 0;
01027   if (soapheaders_){
01028     xmlStream_->startTag(soap_->getEnvelopeUri(),"Header");
01029     serializeHeader();
01030     xmlStream_->endTag(soap_->getEnvelopeUri(),"Header");
01031   }
01032 
01033   xmlStream_->startTag(soap_->getEnvelopeUri(),"Body");
01034   if (style_ == Soap::RPC){
01035     
01036     xmlStream_->startTag(nsp_,op_->getName());
01037   }
01038 
01039   serialize();
01040   if (style_ == Soap::RPC){
01041     xmlStream_->endTag(nsp_,op_->getName());
01042   }
01043 
01044   xmlStream_->endTag(soap_->getEnvelopeUri(),"Body");
01045   xmlStream_->endTag(soap_->getEnvelopeUri(),"Envelope");
01046   xmlStream_->flush();
01047   
01048 
01049 
01050   //test
01051   //  status_ = true;
01052   // if(processResponse)
01053   //   processResults();
01054   // return status_;
01055   //test
01056 
01057   if (dontPost_)
01058     return true;
01059 
01060   post(timeout);
01061   if (!strResults_.empty()){
01062 
01063     if (processResponse)
01064       processResults();
01065 
01066     m_xmlTreeProduced = false;
01067 
01068     if( m_buildXmlTree == true) {
01069 
01070       std::istringstream l_respstr( strResults_);
01071       //std::ifstream l_respstr( "r.xml");//test
01072 
01073       XmlPullParser l_xpp( l_respstr);
01074       l_xpp.setFeature( FEATURE_PROCESS_NAMESPACES, true);
01075       l_xpp.require( XmlPullParser::START_DOCUMENT, "", "");
01076 
01077       m_xmlDoc.clear();
01078 
01079       buildXmlTree( l_xpp, m_xmlDoc.getRootNode());
01080       m_xmlTreeProduced = true;
01081     }
01082     
01083     if (status_)
01084       return true;
01085   }
01086   else{
01087     
01088     if (!op_->getMessage(WsdlPull::Output))
01089       return true; //for web services which have no output
01090 
01091     logger_<<"Couldnt connect to "<<location_;
01092   }
01093   return false;
01094 }
01095 catch (WsdlException we)
01096   {
01097     logger_<<"A WSDL exception occurred at"<<we.line
01098            <<":"<<we.col<<std::endl;
01099     logger_<<we.description<<std::endl;
01100     return false;
01101   }
01102 catch (SchemaParserException spe)
01103   {
01104     logger_<<"A Schema Parser exception occurred at "<<spe.line
01105            <<":"<<spe.col<<std::endl;
01106     logger_<<spe.description<<std::endl;
01107     return false;
01108   }
01109 catch (XmlPullParserException xpe)
01110   {
01111     logger_<<"An Xml Parsing exception occurred at row:col "<<xpe.line
01112            <<":"<<xpe.col<<std::endl;
01113     logger_<<xpe.description<<std::endl;
01114     return false;
01115   }
01116 }
01117 
01118 int
01119 WsdlInvoker::getNextInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum)
01120 {
01121   std::vector<std::string> parents;
01122   return getNextInput(param, type, minimum, maximum, parents);
01123 }
01124 
01125 int
01126 WsdlInvoker::getNextInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum,
01127                           std::vector<std::string> & parents)
01128 {
01129   if (n_ < elems_.size()){
01130     
01131     param = elems_[n_].tag_;
01132     type = elems_[n_].type_;
01133     minimum = elems_[n_].min_;
01134     parents = elems_[n_].parents_;
01135     maximum = elems_[n_].max_;
01136     return n_++;
01137   }
01138   else{
01139     return -1;
01140   }
01141 }
01142 
01143 int
01144 WsdlInvoker::getNextHeaderInput(std::string & param ,Schema::Type & type,
01145                                 int & minimum,int & maximum)
01146 {
01147 
01148   std::vector<std::string> parents;
01149   return getNextHeaderInput(param,type,minimum,maximum,parents);
01150 }
01151 
01152 int
01153 WsdlInvoker::getNextHeaderInput(std::string & param ,Schema::Type & type,
01154                                 int & minimum,int & maximum,
01155                                 std::vector<std::string> & parents)
01156 {
01157   static int h = 0;
01158   if (h<iHeaders_){
01159     param = elems_[h].tag_;
01160     type = elems_[h].type_;
01161     minimum = elems_[h].min_;
01162     maximum = elems_[h].max_;
01163     parents = elems_[h].parents_;
01164     return h++;
01165   }
01166   else{
01167     h = 0;
01168     return -1;
01169   }
01170 }
01171 
01172 void
01173 WsdlInvoker::processResults()
01174 {
01175   XmlPullParser* xpp = 0;
01176   try{
01177 
01178     const Message* m = op_->getMessage(WsdlPull::Output);
01179     std::istringstream respstr(strResults_);
01180     //std::ifstream respstr("response.xml");//test
01181     xpp = new XmlPullParser(respstr);
01182     xpp->setFeature (FEATURE_PROCESS_NAMESPACES, true);
01183     xpp->require (XmlPullParser::START_DOCUMENT, "", "");
01184 
01185     while (status_ && 
01186            xpp->getEventType () != XmlPullParser::END_DOCUMENT) {
01187 
01188       if (xpp->getEventType () == XmlPullParser::END_DOCUMENT)
01189         break;
01190       
01191       if (xpp->getEventType () == XmlPullParser::END_TAG &&
01192           xpp->getName() == "Envelope" &&
01193           xpp->getNamespace() == soap_->getEnvelopeUri())
01194         break;
01195         
01196 
01197       xpp->nextTag();
01198       Qname elemName (xpp->getName ());
01199       elemName.setNamespace(xpp->getNamespace());
01200       
01201       if (elemName.getNamespace() == soap_->getEnvelopeUri()){
01202         
01203         if (elemName.getLocalName() == "Fault"){
01204           processFault(xpp);
01205           status_ = false;
01206           delete xpp;
01207           return;
01208         } 
01209         else if (elemName.getLocalName() == "Header"){
01210 
01211           processHeader(xpp);
01212         }
01213         else if (elemName.getLocalName() == "Body"){
01214 
01215           xpp->nextTag();
01216           processBody(m,xpp);
01217         }
01218       }
01219     }
01220     delete xpp;
01221     n_ = oHeaders_;
01222   }
01223   catch (WsdlException we)
01224     {
01225 
01226       logger_<<"A WSDL exception occurred while parsing the response at line "<<we.line
01227              <<":"<<we.col<<std::endl;
01228       logger_<<we.description<<std::endl;
01229       status_ =false;
01230       if (xpp) delete xpp;
01231     }
01232   catch (SchemaParserException spe)
01233     {
01234       logger_<<"A Schema Parser exception occurred while parsing the response at line "<<spe.line
01235              <<":"<<spe.col<<std::endl;
01236       logger_<<spe.description<<std::endl;
01237       status_ =false;
01238       if (xpp) delete xpp;
01239     }
01240   catch (XmlPullParserException xpe)
01241     {
01242       logger_<<"An Xml Parsing exception occurred while parsing the response at line "<<xpe.line
01243              <<":"<<xpe.col<<std::endl;
01244       logger_<<xpe.description<<std::endl;
01245       status_ =false;
01246       if (xpp) delete xpp;
01247     }
01248   return;
01249 }
01250 
01251 WsdlInvoker::~WsdlInvoker()
01252 {
01253   reset();
01254   if (ourParser_){  
01255       delete ourParser_;
01256   }
01257   if (xmlStream_){
01258     
01259     delete xmlStream_;
01260   }
01261   if (soapstr_){
01262     
01263     delete soapstr_;
01264   }
01265 
01266 #ifdef WITH_CURL
01267   if(ctx) {
01268         curl_easy_cleanup(ctx) ;
01269   }
01270 #endif  
01271 }
01272 
01273 void
01274 WsdlInvoker::reset()
01275 {
01276   n_ =  iHeaders_ = oHeaders_ = 0;
01277   elems_.clear();
01278 
01279   for (size_t x = 0;x<outputs_.size();x++)
01280     delete outputs_[x].second;
01281 
01282   outputs_.clear();
01283   serializeMode_ = false;
01284 
01285 
01286 
01287 }
01288 
01289 bool 
01290 WsdlInvoker::getNextOutput(std::string & name,TypeContainer * & tc)
01291 {
01292   if (status_ && n_ < outputs_.size()){
01293     
01294     name = outputs_[n_].first;
01295     tc = outputs_[n_].second;
01296     n_++;
01297     return true;
01298   }
01299   n_ = oHeaders_;
01300   return false;
01301 }
01302 
01303 
01304 TypeContainer*
01305 WsdlInvoker::getOutput(const std::string  & name)
01306 {
01307   for (unsigned int i = 0 ;status_ && i <outputs_.size();i++){
01308 
01309     if ( name == outputs_[i].first)
01310       return outputs_[i].second;
01311   }
01312   return 0;
01313 }
01314 
01315 bool
01316 WsdlInvoker::getNextHeaderOutput(std::string & name,TypeContainer*& tc)
01317 {
01318   static int j = 0;
01319   if(j<oHeaders_){
01320     name = outputs_[j].first;
01321     tc = outputs_[j].second;
01322     j++;
01323     return true;
01324   }
01325   else{
01326     j = 0;
01327     return false;
01328   }
01329 }
01330 
01331 void * 
01332 WsdlInvoker::getValue(const std::string  & name ,Schema::Type & t)
01333 {
01334   for (unsigned int i = 0 ;status_ && i <outputs_.size();i++){
01335 
01336     if (outputs_[i].second!=0){
01337       outputs_[i].second->rewind();
01338       void * tmp= outputs_[i].second->getValue(name,t);
01339       if (tmp)
01340         return tmp;
01341     }
01342   }
01343   return 0;
01344 }
01345 
01346 //a complete xpath lookup 
01347 std::string
01348 WsdlInvoker::getAsStringFromXPath( const std::string &p_xpath,
01349                                    size_t p_index,
01350                                    std::vector<std::string> *p_array) 
01351 {
01352   //if( status_) {//test
01353   if( status_ && !strResults_.empty()){
01354 
01355     if( p_xpath.empty())
01356       return "";
01357 
01358     if( m_xmlTreeProduced == true) {
01359 
01360       std::vector< std::string> l_results;
01361       m_xmlDoc.xpath( p_xpath, l_results, p_index);
01362 
01363       if( p_array == NULL) {
01364 
01365         if( l_results.empty() == false)
01366           return l_results[ 0];
01367 
01368         return "";
01369       }
01370 
01371       *p_array = l_results;
01372       return "";
01373     }
01374     
01375     //get all the nodes in the expression into an array
01376     std::vector< std::string> l_xpathList;
01377 
01378     size_t l_xpathTotalLevels = 0; // Number of nodes in the xpath expression (not including attribute)
01379     bool l_matchFromRoot = false; // If match must only be made from root node
01380     bool l_doubleSlashMatch = false; //
01381     size_t l_matchAllAtXPathLevel = 0;
01382     bool l_matchAttribute = false; // True if match must be an attribute
01383 
01384 
01385     // Parse the Xpath-like expression
01386     std::string l_tmpElementText; // Temporary string
01387     bool l_seenSlash = false;
01388     for( size_t l_i = 0; l_i < p_xpath.size(); l_i++) {
01389       
01390       if( p_xpath[ l_i] == '/') {
01391         // We have found a xpath node separator: '/'
01392 
01393         if( l_seenSlash == false) {
01394           // No separator has just been seen before
01395           l_seenSlash = true;
01396 
01397           if( l_tmpElementText.empty() == false) {
01398             // if text was collected between 2 separators
01399             // store it in the xpathList
01400             l_xpathList.push_back( l_tmpElementText);
01401             l_tmpElementText.clear();
01402           }
01403         } else { // l_SeenSlash == false
01404           // Two '/' in a row indicate a all-elements match after a certain point
01405           // in the xpath string. Mark the start of the all-elements match
01406           // by inserting an empty string
01407           l_doubleSlashMatch = true;
01408           l_matchAllAtXPathLevel = l_xpathList.size();
01409 
01410           // Clear the "seenSlash" flag
01411           l_seenSlash = false;
01412         }
01413       } else { // xpath[ l_i] == '/'
01414         // Normal char seen
01415 
01416         // if first char is '/' and second is a regular char
01417         // we will have to match from the Xml root level
01418         if( l_i == 1 && l_seenSlash == true)
01419           l_matchFromRoot = true;
01420 
01421         // Mark that we didn't see a separator
01422         l_seenSlash = false;
01423         // Append the text to the temporary string until we find a separator
01424         l_tmpElementText.append( 1, p_xpath[ l_i]);
01425       }
01426     }
01427 
01428     // push the last node (or attribute) into the xpathList (if any)
01429     if( l_tmpElementText.empty() == false)
01430       l_xpathList.push_back( l_tmpElementText);
01431 
01432     // Store the number of xpathTotalLevels that we must traverse
01433     l_xpathTotalLevels = l_xpathList.size();
01434 
01435     if( l_xpathList[ l_xpathTotalLevels - 1][ 0] == '@') {
01436       // If an attribute is to be matched, mark it so
01437       l_matchAttribute = true;
01438       // xpathLevels is decremented as the attribute is not a node to traverse
01439       l_xpathTotalLevels--;
01440     }
01441 
01442     // Parse the XML to deliver the results
01443 
01444     std::istringstream respstr( strResults_);
01445     //std::ifstream respstr( "r.xml");//test
01446 
01447     XmlPullParser l_xpp( respstr);
01448     l_xpp.setFeature( FEATURE_PROCESS_NAMESPACES, true);
01449     l_xpp.require( XmlPullParser::START_DOCUMENT, "", "");
01450 
01451     size_t l_xpathLevel = 0;
01452     size_t l_xmlLevel = 0;
01453     size_t l_failedXpathMatchAtXmlLevel = 0;
01454 
01455     bool l_textWasRetrieved = false;
01456     std::string l_retrievedText;
01457     std::string l_xmlTagName;
01458 
01459     int l_xmlPullEvent;
01460 
01461     do {
01462       l_xmlPullEvent = l_xpp.nextToken();
01463 
01464       if( l_xmlPullEvent == XmlPullParser::START_TAG) {
01465 
01466         l_xmlTagName = l_xpp.getName();
01467 
01468         // Skip envelope and body tags at xml root level
01469         if( l_xmlLevel == 0 && ( l_xmlTagName == "Envelope" || l_xmlTagName == "Body"))
01470           continue;
01471 
01472         // Mark the entrace to xmlLevel
01473         l_xmlLevel++;
01474 
01475         //bool l_doubleSlashMatch = false;
01476         //size_t l_matchAllAtXPathLevel = 0;
01477 
01478         if( l_xmlTagName == l_xpathList[ l_xpathLevel] &&
01479             ( l_failedXpathMatchAtXmlLevel == 0 ||
01480               ( l_doubleSlashMatch == true && l_xpathLevel >= l_matchAllAtXPathLevel))
01481             ) {
01482 
01483           // Check if we must match at root level
01484           // See if "root" levels match (0 for xpathLevel and 1 for xmlLevel)
01485           // if root levels do not match -- skip checks
01486           if( l_matchFromRoot == true)
01487             if( l_xpathLevel == 0 && l_xmlLevel != 1)
01488               continue;
01489 
01490           l_xpathLevel++;
01491 
01492           // If we have not reached the final sought node, carry on
01493           if( l_xpathLevel < l_xpathTotalLevels)
01494             continue;
01495 
01496           // if we have reached the last element of the xpath expression
01497           // and given that all preconditions were met
01498           // store the results
01499 
01500           // Since we have already processed a "start_tag" event the next
01501           // has to be content. "Text" events may be delivered in several
01502           // consecutive events, hence the loop
01503           // Entity references will be shown as independent events
01504 
01505           if( l_matchAttribute == false) {
01506             // We have to store/return the text of the node
01507             // Clear the temporary storage before starting
01508             l_retrievedText.clear();
01509 
01510             do {
01511               // First token after a START_TAG has to be "text or entity" (the returned string might be empty)
01512               l_xmlPullEvent = l_xpp.nextToken();
01513               l_retrievedText += l_xpp.getText();
01514               // Carry on while Text or Entity are returned
01515             } while( l_xmlPullEvent == XmlPullParser::ENTITY_REF || l_xmlPullEvent == XmlPullParser::TEXT);
01516 
01517             // Mark that we have content in "tmp" to be stored or returned
01518             l_textWasRetrieved = true;
01519 
01520           } else {
01521 
01522             // Retrieve the attribue
01523             l_retrievedText = l_xpp.getAttributeValue( "", l_xpathList[ l_xpathLevel].substr( 1));
01524             // Mark that we have content in "tmp" to be stored or returned
01525             l_textWasRetrieved = true;
01526           } 
01527 
01528           if( l_textWasRetrieved == true) {
01529             // If something (node's text or attribute's value) was retrieved
01530             if( p_array == NULL)
01531               return l_retrievedText; // return it, as only one value was sought
01532 
01533             // Store it in the array to be returned
01534             p_array->push_back( l_retrievedText);
01535             // Decrease the xpathLevel, to enable a new match by re-entering the loop
01536             l_xpathLevel--;
01537             
01538             // Clear the "textRetrieved" flag
01539             l_textWasRetrieved = false;
01540           }
01541         } // if( l_xmlTagName == l_xpathList[ l_xpathLevel]) {
01542         else if( l_xpathLevel > 0 && l_failedXpathMatchAtXmlLevel == 0) {
01543           // If a match has already happened (xpathLevel > 0) and we find ourselves here
01544           // the name of the node did not match, we record the xmllevel, so skip
01545           // any deeper tag
01546           // The value will be reset to 0, as soon as END_TAG at the same level is seen
01547           l_failedXpathMatchAtXmlLevel = l_xmlLevel;
01548         }
01549       }
01550 
01551       if( l_xmlPullEvent == XmlPullParser::END_TAG) {
01552 
01553         // Check if we may clear the "failedXpathMatchAtXmlLevel" flag
01554         if( l_failedXpathMatchAtXmlLevel == l_xmlLevel) {
01555           l_failedXpathMatchAtXmlLevel = 0;
01556         }
01557         else if( l_failedXpathMatchAtXmlLevel == 0) {
01558           if( l_xpathLevel > 0 && l_xpp.getName() == l_xpathList[ l_xpathLevel - 1])
01559             l_xpathLevel--;
01560           // Just above. If we have just seen a closing tag that corresponds to the previous xpathLevel
01561           // decrease one xpathLevel (it is 0 based, unlike xmlLevel which is 1 based)
01562         }
01563 
01564         // Skip the envelope and body tags at xml root level
01565         if( l_xmlLevel == 0)
01566           continue;
01567 
01568         l_xmlLevel--;
01569       }
01570 
01571     } while( l_xmlPullEvent != XmlPullParser::END_DOCUMENT);
01572 
01573   } // if (status_ && !strResults_.empty()) 
01574   else {
01575     //throw exception
01576     WsdlException we("Attempted to extract response when web service invocation did not succeed");
01577     throw we;
01578   }
01579  
01580   return "";//nothing found or values returned in vector 'arr'
01581 }
01582 
01583 
01584 
01585 void
01586 WsdlInvoker::post(long timeout, std::string username, std::string passwd)
01587 {
01588   const std::string  postData = soapstr_->str();
01589   if(verbose_){
01590     
01591     std::ofstream ofs("request.log",std::ios::app);
01592     ofs<<postData;
01593     ofs<<std::endl;
01594     ofs.flush();
01595   }
01596     
01597 #ifdef WITH_CURL
01598   CURLcode res;  
01599   std::string strCurlBuffer = "";
01600   if (!ctx){
01601     ctx=curl_easy_init();
01602   }
01603 
01604   if (!ctx)
01605     return ;
01606   curl_easy_setopt( ctx , CURLOPT_URL,  location_.c_str()) ;
01607 
01608   curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , 1 ) ;
01609   if(timeout){
01610     curl_easy_setopt( ctx ,CURLOPT_TIMEOUT, timeout);
01611     curl_easy_setopt( ctx , CURLOPT_CONNECTTIMEOUT, timeout);
01612   }
01613 
01614   if (verbose_) {
01615     curl_easy_setopt( ctx , CURLOPT_VERBOSE,1);
01616     curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , 0 ) ;
01617   }
01618 
01619   curl_easy_setopt( ctx , CURLOPT_POST , 1 );
01620   curl_easy_setopt( ctx , CURLOPT_POSTFIELDS , postData.c_str()) ;
01621   curl_slist* responseHeaders = NULL ;
01622   std::string tmp="SOAPAction: ";
01623   tmp.push_back('"');
01624   tmp+=action_;
01625   tmp.push_back('"');
01626   responseHeaders = curl_slist_append( responseHeaders , tmp.c_str());
01627   responseHeaders = curl_slist_append( responseHeaders ,"Content-Type: text/xml; charset=UTF-8");
01628   responseHeaders = curl_slist_append( responseHeaders ,"Accept: text/xml;");
01629   curl_easy_setopt( ctx , CURLOPT_HTTPHEADER , responseHeaders ) ;
01630   tmp = "wsdlpull";
01631 #ifdef HAVE_CONFIG_H
01632   tmp=tmp+"/"+VERSION;
01633 #endif
01634   curl_easy_setopt( ctx,CURLOPT_USERAGENT,tmp.c_str());
01635   curl_easy_setopt( ctx,CURLOPT_POSTFIELDSIZE,postData.length());
01636   
01637   if (XmlUtils::getProxy()){
01638     curl_easy_setopt(ctx,CURLOPT_PROXY,XmlUtils::getProxyHost().c_str());
01639     tmp=XmlUtils::getProxyUser()+":"+XmlUtils::getProxyPass();
01640     curl_easy_setopt(ctx,CURLOPT_PROXYUSERPWD,tmp.c_str());
01641   }
01642   curl_easy_setopt(ctx, CURLOPT_WRITEDATA, &strCurlBuffer) ;
01643   curl_easy_setopt( ctx ,CURLOPT_WRITEFUNCTION,storeResults) ;
01644 
01645   if (bAuth) {
01646     curl_easy_setopt(ctx, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
01647     std::string tmp = sAuthUser + ":" + sAuthPass;
01648     curl_easy_setopt(ctx, CURLOPT_USERPWD, tmp.c_str());
01649   }
01650   curl_easy_setopt(ctx, CURLOPT_COOKIEFILE, "");
01651   // std::logger_ << "- - - BEGIN: response - - -" << std::endl ;
01652   res=curl_easy_perform(ctx);
01653   //  std::logger_ << "- - - END: response - - -" << std::endl ;
01654 
01655   curl_slist_free_all( responseHeaders ) ;
01656   strResults_ = strCurlBuffer;
01657 
01658 #elif _WIN32
01659         
01660   char* sResults = 0;
01661   XmlUtils::winPost(location_,username,passwd,postData,action_,sResults);
01662   strResults_ = std::string(sResults);
01663 #endif
01664 
01665   if(verbose_ && !strResults_.empty()){
01666     
01667     std::ofstream ofs("response.log",std::ios::app);
01668     ofs<<strResults_;
01669     ofs<<std::endl;
01670     ofs.flush();
01671   }
01672 
01673 }
01674 
01675 void
01676 WsdlInvoker::printTypeNames(bool f)
01677 {
01678   TypeContainer::printTypeNames_ = false;
01679 }
01680 
01681 //build an XML Tree from the results
01682 void
01683 WsdlInvoker::buildXmlTree( XmlPullParser &p_xmlPullParser, XmlNode_t &p_xmlNode, bool p_pendingEvent)
01684 {
01685   int l_xmlPullEvent;
01686 
01687   do {
01688 
01689     if( p_pendingEvent == false) {
01690       l_xmlPullEvent = p_xmlPullParser.nextToken();
01691     } else {
01692       p_pendingEvent = false;
01693       l_xmlPullEvent = p_xmlPullParser.getEventType();
01694     }
01695 
01696     if( l_xmlPullEvent == XmlPullParser::START_TAG) {
01697 
01698       if( p_xmlNode.empty() == true) {
01699 
01700         p_xmlNode.setName( p_xmlPullParser.getName(), XmlNode_t::NON_EMPTY_NODE);
01701 
01702         size_t l_numAttributes = static_cast< size_t>( p_xmlPullParser.getAttributeCount());
01703         for( size_t l_i = 0; l_i < l_numAttributes; l_i++) {
01704 
01705           p_xmlNode.addAttribute( p_xmlPullParser.getAttributeName( l_i),
01706                                   p_xmlPullParser.getAttributeValue( l_i));
01707         }
01708       } else {
01709         XmlNode_t &l_childNodeRef = p_xmlNode.addNode( p_xmlPullParser.getName(), XmlNode_t::EMPTY_NODE);
01710         buildXmlTree( p_xmlPullParser, l_childNodeRef, true);
01711       }
01712     }
01713     else if( l_xmlPullEvent == XmlPullParser::TEXT || l_xmlPullEvent == XmlPullParser::ENTITY_REF) {
01714 
01715       ::std::string l_tmpTxt;
01716       do {
01717         l_tmpTxt += p_xmlPullParser.getText();
01718         l_xmlPullEvent = p_xmlPullParser.nextToken();
01719       } while( l_xmlPullEvent == XmlPullParser::ENTITY_REF || l_xmlPullEvent == XmlPullParser::TEXT);
01720 
01721       p_xmlNode.setText( l_tmpTxt);
01722 
01723       // The previous loop leaves an unprocessed event after calling "nextToken" and seeing
01724       // that it's not text or entity_ref
01725       p_pendingEvent = true;
01726     }
01727     else if( l_xmlPullEvent == XmlPullParser::END_TAG) {
01728       break;
01729     }
01730 
01731   } while( l_xmlPullEvent != XmlPullParser::END_DOCUMENT);
01732 }
01733 
01734 void
01735 WsdlInvoker::processFault(XmlPullParser* xpp)
01736 {
01737 
01738   if (soap_->getSoapVersion() == Soap::SOAP12) {
01739     
01740     while (!(xpp->getEventType() == XmlPullParser::END_TAG && xpp->getName() == "Fault")) {
01741       
01742       if (xpp->getEventType() == XmlPullParser::START_TAG && xpp->getName() == "Code") {
01743         xpp->next();
01744         
01745         while (!(xpp->getEventType() == XmlPullParser::END_TAG && xpp->getName() == "Code")) {
01746           
01747           if (xpp->getEventType() == XmlPullParser::START_TAG && xpp->getName() == "Value") {
01748             xpp->next();
01749             sFaultCode = xpp->getText();
01750             logger_ << "SOAP Fault Code: " << sFaultCode << std::endl;
01751           }
01752           
01753           if (xpp->getEventType() == XmlPullParser::START_TAG && xpp->getName() == "Subcode") {
01754             xpp->next();
01755             
01756             if (xpp->getEventType() == XmlPullParser::START_TAG && xpp->getName() == "Value") {
01757               xpp->next();
01758               sFaultSubCode = xpp->getText();
01759               logger_ << "SOAP Fault SubCode: " << sFaultSubCode << std::endl;
01760             }
01761           }
01762           xpp->next();
01763         }
01764       }
01765       
01766       if (xpp->getEventType() == XmlPullParser::START_TAG && xpp->getName() == "Reason") {
01767         xpp->next();
01768         
01769         if (xpp->getEventType() == XmlPullParser::START_TAG && xpp->getName() == "Text") {
01770           xpp->next();
01771           sFaultString = xpp->getText();
01772           logger_ << "SOAP Fault String: " << sFaultString << std::endl;
01773         }
01774       }
01775       xpp->next();
01776     }
01777   } else {      // SOAP 1.1
01778     
01779     while (!(xpp->getEventType () == XmlPullParser::END_TAG &&
01780              xpp->getName() == "Fault")) {
01781       
01782       if (xpp->getEventType() == XmlPullParser::START_TAG &&
01783           xpp->getName() == "faultcode"){
01784         
01785         xpp->next();
01786         sFaultCode = xpp->getText();
01787         logger_<<"SOAP Fault Code: "<<sFaultCode<<std::endl;
01788       }
01789       
01790       if (xpp->getEventType() == XmlPullParser::START_TAG &&
01791           xpp->getName() == "faultstring"){
01792         
01793         xpp->next();
01794         sFaultString = xpp->getText();
01795         logger_<<"SOAP Fault String: "<<sFaultString<<std::endl;
01796       }
01797       if (xpp->getEventType() == XmlPullParser::START_TAG &&
01798           xpp->getName() == "faultactor"){
01799         
01800         xpp->next();
01801         sFaultActor = xpp->getText();
01802         logger_<<"SOAP Fault Actor: "<<sFaultActor<<std::endl;
01803       }
01804       xpp->next();
01805     }
01806   }
01807 }
01808 
01809 void 
01810 WsdlInvoker::processBody(const Message* m,
01811                          XmlPullParser* xpp)
01812 {
01813   
01814   if (xpp->getName() == "Fault") {
01815     
01816     processFault(xpp);
01817     status_ = false;
01818     return;
01819   }
01820 
01821   if (style_ == Soap::RPC && use_==Soap::ENCODED){
01822           
01823     if (xpp->getName () == op_->getName()+"Response") {
01824 
01825       //operation's name followed by 'Response' must be the containing element
01826       xpp->nextTag ();
01827       
01828       do {
01829       
01830         
01831         //first look for xsi:type
01832         Qname typ(xpp->getAttributeValue(Schema::SchemaInstaceUri, "type"));
01833         typ.setNamespace(xpp->getNamespace(typ.getPrefix()));
01834         const SchemaParser * sParser = 0;
01835         int typeId = 0;
01836           
01837         if (!(typ.getNamespace() == soap_->getEncodingUri() &&
01838               typ.getLocalName() == "Array"))//for soap array just use the part's type info
01839           sParser= wParser_->getSchemaParser(typ.getNamespace());
01840           
01841         if (sParser){
01842             
01843           typeId = (const_cast<SchemaParser*>(sParser))->getTypeId(typ);
01844         }
01845         else{
01846 
01847           //if xsi:type doesnt give a clue then see if the part name matches
01848           const Part * p = m->getMessagePart(xpp->getName ());
01849           if (p){
01850             
01851             sParser = wParser_->getSchemaParser(p->schemaId());
01852             typeId = p->type();
01853           }else {
01854 
01855 
01856           }
01857         }
01858         if (sParser && typeId !=0){  
01859             
01860           SchemaValidator * sv= new SchemaValidator(sParser);     
01861           std::string tag = xpp->getName();
01862           TypeContainer * t = sv->validate (xpp, typeId);
01863           outputs_.push_back(std::pair<std::string,TypeContainer*>(tag,t));
01864           xpp->nextTag();
01865           delete sv;
01866         }
01867         else{
01868 
01869           status_ = false;
01870           logger_<<"Unknown element "<<xpp->getName()<<std::endl;
01871           return;
01872         }
01873       } while (!(xpp->getName() == op_->getName()+"Response" &&
01874                  xpp->getEventType() == XmlPullParser::END_TAG));
01875     }
01876   }
01877   else{
01878     
01879     while (!(xpp->getName() == "Body" && 
01880              xpp->getNamespace() == soap_->getEnvelopeUri() &&
01881              xpp->getEventType() == XmlPullParser::END_TAG)) {
01882              
01883       Qname elemName (xpp->getName ());
01884       elemName.setNamespace(xpp->getNamespace());
01885 
01886       //doc/literal has ref type element in the part
01887       const SchemaParser * sParser =
01888         wParser_->getSchemaParser(elemName.getNamespace());
01889       if (!sParser){
01890           
01891         status_ = false;
01892         logger_<<"Unknown element "<<elemName<<std::endl;
01893         return;
01894       }
01895       SchemaValidator * sv= new SchemaValidator(sParser);         
01896           
01897       const Element * e = sParser->getElement (elemName);
01898       if(e){
01899         int typeId = e->getType () ;
01900         TypeContainer * t = sv->validate (xpp, typeId);
01901         std::pair<std::string,TypeContainer*> pr(elemName.getLocalName(),t);
01902         outputs_.push_back(pr);
01903       }
01904       else{
01905         status_ = false;
01906         std::cerr<<"Unknown element "<<elemName.getLocalName()<<std::endl;
01907         return;
01908       }
01909       delete sv;
01910       xpp->nextTag();
01911     }
01912   }
01913   status_ = true;
01914 }
01915 
01916 void
01917 WsdlInvoker::processHeader(XmlPullParser *xpp)
01918 {
01919   Qname elem;
01920   const SchemaParser * sParser = 0;
01921   int type = Schema::XSD_INVALID;
01922   xpp->nextTag ();
01923   std::string tag = xpp->getName();
01924 
01925   while (!(xpp->getEventType() == XmlPullParser::END_TAG &&
01926            xpp->getName() == "Header")){
01927 
01928 
01929     //first look for xsi:type
01930     if (xpp->getAttributeValue(Schema::SchemaInstaceUri, "type") != "" ) {
01931       
01932       elem = Qname(xpp->getAttributeValue(Schema::SchemaInstaceUri, "type"));
01933       elem.setNamespace(xpp->getNamespace(elem.getPrefix()));
01934       sParser= wParser_->getSchemaParser(elem.getNamespace());
01935       type = (const_cast<SchemaParser*>(sParser))->getTypeId(elem);  
01936     }
01937     else {
01938 
01939       elem = Qname(xpp->getName());
01940       elem.setNamespace(xpp->getNamespace());      
01941       sParser=wParser_->getSchemaParser(elem.getNamespace());
01942       const Element * e = sParser->getElement (elem);
01943       if(e){
01944              type = e->getType ();
01945       }
01946     }
01947     SchemaValidator * sv= new SchemaValidator(sParser);   
01948     TypeContainer * t = sv->validate (xpp, type);
01949     outputs_.push_back(std::pair<std::string,TypeContainer*>(tag,t));
01950     oHeaders_++; 
01951     xpp->nextTag();
01952     delete sv;
01953   }
01954 }
01955 
01956 bool
01957 WsdlInvoker::isSoapArray (const ComplexType * ct,
01958                           const SchemaParser * sParser)
01959 {
01960   const XSDType * baseType=sParser->getType(ct->getBaseTypeId());
01961   if (baseType) {
01962     if(baseType->getNamespace()==soap_->getEncodingUri() &&
01963        baseType->getName()=="Array")
01964       return true;
01965   }
01966   return false;
01967 }
01968 
01969 void
01970 WsdlInvoker::setCredentials(const std::string & user, const std::string & pass)
01971 {
01972   username_ = user;
01973   password_ = pass;
01974   XmlUtils::setProxyUser(user);
01975   XmlUtils::setProxyPass(pass);
01976   XmlUtils::setProxy(true);
01977 }
01978 
01979 void
01980 WsdlInvoker::setBuildXmlTree( bool p_buildXmlTree)
01981 {
01982   m_buildXmlTree = p_buildXmlTree;
01983 }
01984 
01985 bool
01986 WsdlInvoker::getBuildXmlTree( void) const
01987 {
01988   return m_buildXmlTree;
01989 }
01990 
01991 void
01992 WsdlInvoker::setProcessEnvAndBody( bool p_processEnvAndBody)
01993 {
01994   m_xmlDoc.setProcessEnvAndBody( p_processEnvAndBody);
01995 }
01996 
01997 bool
01998 WsdlInvoker::getProcessEnvAndBody( void) const
01999 {
02000   return m_xmlDoc.getProcessEnvAndBody();
02001 }
02002 
02003 void
02004 WsdlInvoker::setLazyRelativeMatch( bool p_lazyRelativeMatch)
02005 {
02006   m_xmlDoc.setLazyRelativeMatch( p_lazyRelativeMatch);
02007 }
02008 
02009 bool
02010 WsdlInvoker::getLazyRelativeMatch( void) const
02011 {
02012   return m_xmlDoc.getLazyRelativeMatch();
02013 
02014 }
02015 
02016 void
02017 WsdlInvoker::setAuth(const std::string & user, const std::string & pass)
02018 {
02019   sAuthUser = user;
02020   sAuthPass = pass;
02021   bAuth = true;
02022 }
02023 
02024 void
02025 WsdlInvoker::setProxy(const std::string & host,int  port)
02026 {
02027   host_ = host;
02028   port_ = port;
02029   std::ostringstream oss;
02030   oss<<host<<":"<<port;
02031   XmlUtils::setProxyHost(oss.str());
02032   XmlUtils::setProxy(true);
02033 }
02034 
02035 std::string
02036 WsdlInvoker::getPrefix(const std::string & nsp)
02037 {
02038   
02039   unsigned int i = 0;
02040   char prefix='1';
02041   while (i<prefixes_.size()) {
02042     if (prefixes_[i] == nsp)
02043       break;
02044     i++;
02045   }
02046 
02047   std::string tmp("ns");
02048   tmp.append(1,prefix+i);
02049   if (i == prefixes_.size())
02050     prefixes_.push_back(nsp);
02051   
02052   return tmp;
02053 
02054 }
02055 
02056 }
02057 
02058 #ifdef WITH_CURL
02059 size_t
02060 storeResults(void * buf,size_t sz,size_t nmemb,void* userdata)
02061 {
02062     char* sBuffer = (char*) buf;
02063     std::string* strCurlBuffer = (std::string*) userdata;
02064 
02065     int result = 0;
02066     if (strCurlBuffer) {
02067         strCurlBuffer->append(sBuffer, sz * nmemb);
02068         result = sz * nmemb;
02069     }
02070 
02071     return result;
02072 }
02073 #endif 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by  doxygen 1.6.2