src/wsdlparser/WsdlInvoker.cpp

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 
00024 #ifdef  WITH_CURL
00025 #include <curl/curl.h>
00026 #endif 
00027 #include "wsdlparser/WsdlInvoker.h"
00028 
00029 extern "C" {
00030   size_t storeResults(void * buf,size_t sz,size_t nmemb,void* userdata);
00031 }
00032 static char* results_ = 0;
00033 
00034 namespace WsdlPull {
00035 
00036 WsdlInvoker::WsdlInvoker()
00037   :wParser_(0),
00038    ourParser_(0),
00039    xmlStream_(0),
00040    soap_(0),
00041    hMessage_(0),
00042    hPartId_(-1),
00043    soapstr_(0),
00044    status_(false),
00045    serializeMode_(false),
00046    verbose_(false),
00047    oHeaders_(0),
00048    op_(0),
00049    n_(0),
00050    iHeaders_(0),
00051    messageType_(WsdlPull::Input)
00052 {
00053 }
00054 
00055 WsdlInvoker::WsdlInvoker(const std::string & url)
00056   :wParser_(0),
00057    ourParser_(0),
00058    xmlStream_(0),
00059    soap_(0),
00060    hMessage_(0),
00061    hPartId_(-1),
00062    status_(false),
00063    serializeMode_(false),
00064    verbose_(false),
00065    op_(0),
00066    n_(0),
00067    iHeaders_(0),
00068    messageType_(WsdlPull::Input)
00069 {
00070   parseWsdl(url);
00071 }
00072 
00073 void
00074 WsdlInvoker::parseWsdl(const std::string & url)
00075 {
00076   try{
00077     wParser_ = new WsdlParser(url,logger_);
00078     ourParser_= wParser_;
00079     if (wParser_){
00080       //parse the web service
00081       while (wParser_->getNextElement () != WsdlParser::END);
00082       if (wParser_->status()){
00083       
00084         status_=true;
00085         init(wParser_);
00086       }
00087     }
00088   }
00089     catch (WsdlException we)
00090       {
00091        logger_<<"An Exception occurred at "<<we.line   
00092              <<":"<<we.col<<std::endl;
00093         logger_<<we.description<<std::endl;
00094         status_ =false;
00095       }
00096     catch (SchemaParserException spe)
00097       {
00098        logger_<<"An Exception occurred at "<<spe.line
00099              <<":"<<spe.col<<std::endl;
00100         logger_<<spe.description<<std::endl;
00101         status_ =false;
00102       }
00103     catch (XmlPullParserException xpe)
00104       {
00105        logger_<<"An Exception occurred at "<<xpe.line
00106              <<":"<<xpe.col<<std::endl;
00107        logger_<<xpe.description<<std::endl;
00108        status_= false;
00109       }
00110 }
00111 
00112 bool
00113 WsdlInvoker::init(WsdlParser* parser)
00114 {
00115   try{
00116     wParser_ = parser;
00117     status_ = wParser_->status();
00118     if (status_){
00119       
00120       PortType::cPortTypeIterator p1,p2;
00121       wParser_->getPortTypes(p1,p2);
00122       int i=0;
00123       Soap* soap=static_cast<Soap*> (wParser_->getExtensibilityHandler(Soap::soapBindingUri));
00124       while(p1!=p2){
00125     
00126         Operation::cOpIterator op1,op2;
00127         (*p1)->getOperations(op1,op2);
00128         const Binding *bn = (*p1)->binding(Soap::soapBindingUri);
00129         if (!bn){
00130           p1++;
00131           continue;
00132         }
00133         int soap_binding_elem =soap->getElementName (bn->getBindingInfo ());
00134         //check if the port type has a soap binding
00135         if (soap_binding_elem == 0){
00136           p1++;
00137           continue;
00138         }
00139 
00140         while(op1!=op2){
00141         
00142           opMap_[(*op1)->getName()]=*op1;
00143           op1++; 
00144           i++;
00145         }
00146         p1++;
00147       }
00148     }
00149   }
00150   catch (WsdlException we)
00151     {
00152       logger_<<"An Exception occurred at "<<we.line
00153              <<":"<<we.col<<std::endl;
00154       logger_<<we.description<<std::endl;
00155       status_ =false;
00156     }
00157   catch (SchemaParserException spe)
00158     {
00159       logger_<<"An Exception occurred at "<<spe.line
00160              <<":"<<spe.col<<std::endl;
00161       logger_<<spe.description<<std::endl;
00162       status_ =false;
00163     }
00164   catch (XmlPullParserException xpe)
00165     {
00166       logger_<<"An Exception occurred at "<<xpe.line
00167              <<":"<<xpe.col<<std::endl;
00168       logger_<<xpe.description<<std::endl;
00169       status_ =false;
00170     }
00171   return status_;
00172 }
00173  
00174 int
00175 WsdlInvoker::getOperations(std::vector<std::string> & operations)
00176 {
00177   int i = 0;
00178   for(
00179   std::map<std::string,const Operation*>::iterator it =
00180     opMap_.begin();
00181   it != opMap_.end();
00182   it++,i++){
00183 
00184     operations.push_back(it->first);
00185   }
00186   return i;
00187 }
00188 
00189 std::string
00190 WsdlInvoker::getOpDocumentaion(const std::string & n)
00191 {
00192   
00193   std::map<std::string,const Operation*>::iterator it =
00194     opMap_.find(n);
00195   
00196   if (it != opMap_.end()){
00197     
00198     return  it->second->getDocumentation();
00199   }
00200   return "";
00201 }
00202 
00203 bool
00204 WsdlInvoker::setOperation(const std::string & opname,
00205                           WsdlPull::MessageType mType)
00206 {
00207   reset();
00208   messageType_ = mType;
00209    std::map<std::string,const Operation*>::iterator it =
00210     opMap_.find(opname);
00211 
00212   if (it != opMap_.end()){
00213     
00214     op_ = it->second;
00215 
00216     getOperationDetails(op_);
00217     
00218     if (hMessage_){
00219       serializeHeader();
00220     }
00221     serialize();
00222     n_ = iHeaders_;
00223     return true;
00224   }
00225   else{
00226     return false;
00227   }
00228 }
00229 
00230 std::string
00231 WsdlInvoker::getServiceEndPoint(const std::string & opname) 
00232 {
00233 
00234   reset();
00235   location_="";
00236   std::map<std::string,const Operation*>::iterator it =
00237     opMap_.find(opname);
00238 
00239   if (it != opMap_.end()){
00240     
00241     const Operation* op = it->second;
00242 
00243     getOperationDetails(op);
00244     reset();
00245   }
00246   return location_;
00247 }
00248 
00249 void
00250 WsdlInvoker::getOperationDetails(const Operation* op) 
00251 {
00252   const Binding * bnSoap = op->portType()->binding(Soap::soapBindingUri);
00253   soap_ = static_cast<Soap*> (wParser_->getExtensibilityHandler(Soap::soapBindingUri));    
00254 
00255   ///get various soap properties
00256   soap_->getServiceLocation (bnSoap->getServiceExtId (),location_);
00257   style_ = soap_->getStyle();
00258 
00259   //get the soap:operation's SOAPAction and style
00260   const int *bindings = 0;
00261   int opIndex  = op->portType()->getOperationIndex(op->getName());
00262   bnSoap->getOpBinding (opIndex, bindings);
00263   int soapOpBindingId = bindings[0];
00264   //operation's style over rides 
00265   soap_->getSoapOperationInfo (soapOpBindingId, action_, style_);
00266 
00267   //get the soap:body namespace and use attributes
00268   int nBindings=bnSoap->getInputBinding(opIndex,bindings);
00269   //get the body and header
00270   for (int x=0;x<nBindings;x++){
00271     if (soap_->isSoapBody(bindings[x])){
00272 
00273       soap_->getSoapBodyInfo(bindings[x],nsp_,use_,encodingStyle_);
00274     }
00275     if (soap_->isSoapHeader(bindings[x]))
00276       soap_->getSoapHeaderInfo(bindings[x],hPartId_,hMessage_);
00277   }
00278     
00279   if (nsp_.empty()){
00280 
00281     nsp_ = wParser_->getNamespace();
00282   }
00283 }
00284 
00285 void
00286 WsdlInvoker::serializeHeader()
00287 {
00288   //create input  holders for the soap header,use the same list
00289   //but just remember where the header's params end
00290   std::string name;
00291   Schema::Type pType =Schema::XSD_INVALID;
00292   if (hMessage_->getPartRefType(hPartId_)==Part::Type){
00293     name = hMessage_->getMessagePart(hPartId_)->element()->getName();
00294     pType = (Schema::Type)hMessage_->getMessagePart(hPartId_)->element()->getType();
00295   }
00296   else {
00297     name = hMessage_->getPartName(hPartId_);
00298     pType = (Schema::Type)hMessage_->getMessagePart(hPartId_)->type();
00299   }
00300   std::vector<std::string> parents;
00301   parents.push_back(name);
00302   serializeType(pType,
00303                 name,
00304                 wParser_->getSchemaParser(hMessage_->getPartContentSchemaId(hPartId_)),
00305                 1,1,parents);
00306   iHeaders_ = elems_.size();
00307 }
00308 
00309 //this method extracts the  atomic types needed for the web service
00310 //it recursively calls serializeType for all the input or output types expected
00311 //This method works in 2 modes.In the serializeMode_ == false it creates holders
00312 //for the parameter values.In serializeMode_ == true it uses the inputs from the holders 
00313 //to generate the SOAP XML message
00314 void
00315 WsdlInvoker::serialize()
00316 {
00317   const Message * m = op_->getMessage(messageType_);
00318   if (!m)
00319     return;
00320   
00321   for (int i = 0 ;i<m->getNumParts();i++){
00322       
00323     Part::PartRefType prt = m->getPartRefType(i);
00324     const Part * p = m->getMessagePart(i);
00325     const SchemaParser * sParser = wParser_->getSchemaParser(p->schemaId());
00326     
00327     std::vector<std::string> parents;
00328     if (prt == Part::Elem){
00329       
00330       const Element * e = p->element();
00331       serializeType((Schema::Type)e->getType(),e->getName(),sParser,1,1,parents);
00332     }
00333     else{
00334       
00335       serializeType((Schema::Type)p->type(),p->name(),sParser,1,1,parents);
00336     }
00337   }
00338 }
00339 
00340 void
00341 WsdlInvoker::serializeType(Schema::Type typeId,
00342                            const std::string &tag,
00343                            const SchemaParser * sParser,
00344                            int minimum,
00345                            int maximum,
00346                            std::vector<std::string> parents)
00347 {
00348   std::string t = tag;
00349   if (t == "*")
00350     t = "item";
00351 
00352   const XSDType * pType = sParser->getType(typeId);
00353   if ( pType== 0 ||
00354        pType->isSimple() ||
00355        pType->getContentModel() == Schema::Simple){
00356     
00357     if (serializeMode_ == false){
00358       
00359       parents.push_back(tag);
00360       Parameter p(typeId,t,minimum,maximum,sParser,parents);
00361       elems_.push_back(p);
00362     }
00363     else{
00364       //generate the xml
00365       serializeParam(n_++,t,sParser);
00366     }
00367   }
00368   else{
00369 
00370     if (serializeMode_){
00371       
00372       if (style_ == Soap::DOC){
00373     
00374         xmlStream_->setPrefix("s",sParser->getNamespace());
00375         xmlStream_->startTag(sParser->getNamespace(),t);
00376       }
00377       else{
00378 
00379         xmlStream_->startTag("",t);
00380 
00381         //fix for sending SOAP arrays.add the soap arrayType attribute
00382         //works only for 1-D arrays
00383         const ComplexType* ct = static_cast<const ComplexType*>(pType);
00384         if(isSoapArray(ct,sParser)){
00385 
00386           std::string arrayName = ct->getName();
00387           arrayName = "ns:"+arrayName+"[1]";
00388           xmlStream_->attribute(Soap::soapEncUri,"arrayType",arrayName);
00389         }
00390       }
00391     }
00392     
00393     const ComplexType * ct =
00394       static_cast<const ComplexType*>(pType);
00395     
00396     //complex types handling
00397     if (ct->getNumAttributes() > 0) {
00398       
00399       for (int i = 0; i < ct->getNumAttributes(); i++) {
00400           
00401         const Attribute*at = ct->getAttribute(i);
00402         /*
00403          * Check for the correctness of each attribute
00404          */
00405         if (at->isRequired()){
00406         
00407           if (serializeMode_ == false){
00408 
00409             std::vector<std::string> attparents(parents);
00410             attparents.push_back(tag);
00411             attparents.push_back("#" + at->getName() + "#");
00412             Parameter p((Schema::Type)at->getType(),at->getName(),elems_.size(),0,sParser,
00413                         attparents);
00414             elems_.push_back(p);
00415           }
00416           else{
00417             //generate the xml
00418             
00419             xmlStream_->attribute(sParser->getNamespace(),at->getName(),elems_[n_++].data_[0]);
00420           }
00421         }
00422         else
00423           continue;
00424       }
00425     }
00426   
00427     if (ct->getContentModel() == Schema::Simple) {
00428 
00429       if (serializeMode_ == false){
00430       
00431         parents.push_back(tag);
00432         Parameter p((Schema::Type)ct->getContentType(),tag,minimum,maximum,sParser,parents);
00433         elems_.push_back(p);
00434       }
00435       else{
00436         //generate the xml
00437         serializeParam(n_++,t,sParser);
00438       }
00439     }
00440     else{
00441           
00442       ContentModel* cm=ct->getContents();
00443       if(cm){
00444 
00445         parents.push_back(tag);
00446         serializeContentModel(cm,sParser,parents);
00447       }
00448     }
00449 
00450     if (serializeMode_){
00451 
00452       if (style_ == Soap::DOC){
00453     
00454         xmlStream_->endTag(sParser->getNamespace(),tag);
00455       }
00456       else{
00457         
00458         xmlStream_->endTag("",t);
00459       }
00460     }
00461   }
00462 }
00463 
00464 void
00465 WsdlInvoker::serializeContentModel(ContentModel *cm,
00466                                    const SchemaParser *sParser,
00467                                    std::vector<std::string> parents)
00468 {
00469   
00470   ContentModel::ContentsIterator cit_b=cm->begin();
00471   ContentModel::ContentsIterator cit_e=cm->end();
00472   ContentModel::ContentsIterator ci=cit_b;
00473 
00474   switch (cm->getCompositor())
00475     {
00476     case Schema::All:
00477     case Schema::Sequence:
00478     case Schema::Choice:
00479       {
00480         // a simple logic to start with
00481         // not taking care of all,choice ,sequence as of now
00482         
00483         for (ci=cit_b;ci!=cit_e;ci++){
00484           
00485           if(ci->second==ContentModel::Particle &&
00486              ci->first.e->getMax() > 0){
00487 
00488             const SchemaParser * s1Parser = sParser;
00489             const XSDType * type = sParser->getType(ci->first.e->getType());
00490             if (type && 
00491                 type->getNamespace() != sParser->getNamespace()) {
00492 
00493               s1Parser = wParser_->getSchemaParser(type->getNamespace());
00494             }
00495                                                           
00496             serializeType((Schema::Type)ci->first.e->getType(),
00497                           ci->first.e->getName(),
00498                           s1Parser,
00499                           ci->first.e->getMin(),
00500                           ci->first.e->getMax(),
00501                           parents);
00502           }
00503           else if (ci->second==ContentModel::Container) {
00504             
00505             //nested xsd:sequence inside choice..nested content models
00506             serializeContentModel(ci->first.c,
00507                                   sParser,
00508                                   parents);
00509               
00510           }
00511           else if (ci->second==ContentModel::ParticleGroup){
00512             
00513             //xsd:group inside 
00514             serializeContentModel(ci->first.g->getContents(),
00515                                   sParser,
00516                                   parents);
00517           }
00518         }
00519         break;
00520       }
00521     }
00522 }
00523 
00524 
00525 void
00526 WsdlInvoker::serializeParam(int n,const std::string & tag,
00527                             const SchemaParser * sParser)
00528 {
00529 
00530   std::string t=tag;
00531   if (tag=="*")
00532     t="item";
00533     
00534   for (int i = 0 ;i<elems_[n].n_;i++){
00535 
00536     if (style_ == Soap::DOC){
00537     
00538       xmlStream_->setPrefix("s",sParser->getNamespace());
00539       xmlStream_->startTag(sParser->getNamespace(),t);
00540     }
00541     else{
00542       
00543         xmlStream_->startTag("",t);
00544 
00545       //xsi::type is needed for many SOAP servers
00546       if (sParser->isBasicType(elems_[n].type_)){
00547 
00548         xmlStream_->attribute(Schema::SchemaInstaceUri,
00549                               "type",
00550                               "xsd:"+sParser->getTypeName(elems_[n].type_));
00551       }
00552     }
00553     
00554     xmlStream_->text(elems_[n].data_[i]);
00555         
00556     if (style_ == Soap::DOC){
00557     
00558       xmlStream_->endTag(sParser->getNamespace(),t);
00559     }
00560     else{
00561 
00562       xmlStream_->endTag("",t);
00563     }
00564   }
00565 }
00566 
00567 
00568 bool
00569 WsdlInvoker::setInputValue(const int param,void** values,unsigned int occurs)
00570 {
00571 
00572   if (occurs < elems_[param].min_ ||
00573       occurs > elems_[param].max_)
00574     return false;
00575 
00576   SchemaValidator *sv = new SchemaValidator (elems_[param].sParser_);
00577   for (unsigned int i = 0 ;i < occurs ;i++){
00578       
00579     TypeContainer * tc = sv->validate(values[i],
00580                                       elems_[param].type_);
00581     if (!tc->isValueValid()){
00582         
00583       return false;
00584     }
00585     std::ostringstream oss;
00586     tc->print(oss);
00587     elems_[param].data_.push_back(oss.str());
00588     delete tc;
00589   }
00590   delete sv;
00591   
00592   elems_[param].n_ = occurs;
00593   return true;
00594 }
00595 
00596 bool
00597 WsdlInvoker::setInputValue(const int param,std::vector<std::string> values)
00598 {
00599 
00600 
00601   if (values.size() < elems_[param].min_ ||
00602       values.size() > elems_[param].max_)
00603     return false;
00604 
00605   SchemaValidator *sv = new SchemaValidator (elems_[param].sParser_);
00606   
00607   for (size_t i = 0 ;i < values.size() ;i++){
00608       
00609     TypeContainer * tc = sv->validate(values[i],
00610                                       elems_[param].type_);
00611     if (!tc->isValueValid()){
00612         
00613       return false;
00614     }
00615     elems_[param].data_.push_back(values[i]);
00616     delete tc;
00617   }
00618   delete sv;
00619   
00620   elems_[param].n_ = values.size();
00621   return true;
00622 }
00623 
00624 bool
00625 WsdlInvoker::setInputValue(const int param,std::string val)
00626 {
00627 
00628   const SchemaParser* sParser = elems_[param].sParser_;
00629   SchemaValidator *sv = new SchemaValidator (sParser);
00630   Schema::Type t = elems_[param].type_;
00631   const XSDType * pType = sParser->getType(t);
00632   if (pType && !pType->isSimple()){
00633 
00634     if (pType->getContentModel() != Schema::Simple)
00635       return false;
00636 
00637     const ComplexType * ct = static_cast<const ComplexType*>(pType);
00638     t = (Schema::Type)ct->getContentType();
00639   }
00640   
00641   TypeContainer * tc = sv->validate(val,t);
00642   if (!(tc && tc->isValueValid())){
00643         
00644     return false;
00645   }
00646   if (elems_[param].data_.size() == 0)
00647     elems_[param].data_.push_back(val);
00648   else
00649     elems_[param].data_[0]=val;
00650 
00651   delete tc;
00652     
00653   delete sv;
00654   
00655   elems_[param].n_ = 1;
00656   return true;
00657 }
00658 
00659 
00660 
00661 bool
00662 WsdlInvoker::setInputValue(const int param,void* val)
00663 {
00664 
00665   const SchemaParser*  sParser = elems_[param].sParser_;
00666   SchemaValidator *sv = new SchemaValidator (sParser);
00667   Schema::Type t = elems_[param].type_;
00668   const XSDType * pType = sParser->getType(t);
00669   if (pType && !pType->isSimple()){
00670 
00671     if (pType->getContentModel() != Schema::Simple)
00672       return false;
00673 
00674     const ComplexType * ct = static_cast<const ComplexType*>(pType);
00675     t = (Schema::Type)ct->getContentType();
00676   }
00677 
00678   TypeContainer * tc = sv->validate(val,t);
00679   if (!(tc && tc->isValueValid())){
00680         
00681     return false;
00682   }
00683   std::ostringstream oss;
00684   tc->print(oss);
00685   if (elems_[param].data_.size() == 0)
00686     elems_[param].data_.push_back(oss.str());
00687   else
00688     elems_[param].data_[0]=oss.str();
00689   delete tc;
00690   delete sv;
00691   elems_[param].n_ = 1;
00692   return true;
00693 }
00694 
00695 bool
00696 WsdlInvoker::setValue(const std::string & param,void* val)
00697 {
00698   for (size_t s = 0;s<elems_.size();s++){
00699     
00700     if (elems_[s].tag_ == param)
00701       return setInputValue(s,val);
00702   }
00703   return false;
00704 }
00705 
00706 bool
00707 WsdlInvoker::setValue(const std::string & param,void** values,unsigned int occur)
00708 {
00709 
00710   for (size_t s = 0;s<elems_.size();s++){
00711     
00712     if (elems_[s].tag_ == param)
00713       return setInputValue(s,values,occur);
00714   }
00715   return false;
00716 }
00717  
00718 bool
00719 WsdlInvoker::setValue(const std::string & param,std::string val)
00720 {
00721   for (size_t s = 0;s<elems_.size();s++){
00722     
00723     if (elems_[s].tag_ == param)
00724       return setInputValue(s,val);
00725   }
00726   return false;
00727 }
00728 
00729 bool
00730 WsdlInvoker::setValue(const std::string & param,std::vector<std::string> values)
00731 {
00732   for (size_t s = 0;s<elems_.size();s++){
00733     
00734     if (elems_[s].tag_ == param)
00735       return setInputValue(s,values);
00736   }
00737   return false;
00738 }
00739 
00740 
00741 bool
00742 WsdlInvoker::invoke(long timeout)
00743 {
00744 
00745   if (xmlStream_){
00746     
00747     delete xmlStream_;
00748   }
00749   if (soapstr_){
00750     
00751     delete soapstr_;
00752   }
00753   if (results_){
00754     delete results_;
00755     results_ = 0;
00756   }
00757 
00758   for (size_t x = 0;x<outputs_.size();x++)
00759     delete outputs_[x].second;
00760 
00761   outputs_.clear();
00762 
00763   soapstr_ = new std::ostringstream();
00764   xmlStream_ = new XmlSerializer(*soapstr_);
00765   
00766   serializeMode_ = true;
00767   xmlStream_->setPrefix("ns",nsp_);
00768   xmlStream_->startDocument("UTF-8",false);
00769   xmlStream_->setPrefix("SOAP-ENV",Soap::soapEnvUri);
00770   xmlStream_->setPrefix("SOAP-ENC",Soap::soapEncUri);
00771   xmlStream_->setPrefix("xsd",Schema::SchemaUri);
00772   xmlStream_->setPrefix("xsi",Schema::SchemaInstaceUri);
00773   xmlStream_->startTag(Soap::soapEnvUri,"Envelope");
00774   
00775   if (style_ == Soap::RPC) {
00776     
00777     xmlStream_->attribute(Soap::soapEnvUri,
00778                           "encodingStyle",
00779                           Soap::soapEncUri);
00780   }
00781 
00782   n_ = 0;
00783   if (hMessage_){
00784     xmlStream_->startTag(Soap::soapEnvUri,"Header");
00785     serializeHeader();
00786     xmlStream_->endTag(Soap::soapEnvUri,"Header");
00787   }
00788 
00789   xmlStream_->startTag(Soap::soapEnvUri,"Body");
00790   if (style_ == Soap::RPC){
00791     
00792     xmlStream_->startTag(nsp_,op_->getName());
00793   }
00794 
00795   serialize();
00796   if (style_ == Soap::RPC){
00797     xmlStream_->endTag(nsp_,op_->getName());
00798   }
00799 
00800   xmlStream_->endTag(Soap::soapEnvUri,"Body");
00801   xmlStream_->endTag(Soap::soapEnvUri,"Envelope");
00802   xmlStream_->flush();
00803   
00804 
00805 
00806   //test
00807   //      status_ = true;
00808   //      processResults();
00809   //      return status_;
00810   //test
00811   post(timeout);
00812   if (results_){
00813     processResults();
00814     if (status_)
00815       return true;
00816   }
00817   else{
00818     
00819     logger_<<"Couldnt connect to "<<location_;
00820   }
00821     
00822   return false;
00823 }
00824 
00825 int
00826 WsdlInvoker::getNextInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum)
00827 {
00828   std::vector<std::string> parents;
00829   return getNextInput(param, type, minimum, maximum, parents);
00830 }
00831 
00832 int
00833 WsdlInvoker::getNextInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum,
00834                           std::vector<std::string> & parents)
00835 {
00836   if (n_ < elems_.size()){
00837     
00838     param = elems_[n_].tag_;
00839     type = elems_[n_].type_;
00840     minimum = elems_[n_].min_;
00841     parents = elems_[n_].parents_;
00842     maximum = elems_[n_].max_;
00843     return n_++;
00844   }
00845   else{
00846     return -1;
00847   }
00848 }
00849 
00850 int
00851 WsdlInvoker::getNextHeaderInput(std::string & param ,Schema::Type & type,
00852                                 int & minimum,int & maximum)
00853 {
00854 
00855   std::vector<std::string> parents;
00856   return getNextHeaderInput(param,type,minimum,maximum,parents);
00857 }
00858 
00859 int
00860 WsdlInvoker::getNextHeaderInput(std::string & param ,Schema::Type & type,
00861                                 int & minimum,int & maximum,
00862                                 std::vector<std::string> & parents)
00863 {
00864   static int  h=0;
00865   if (h<iHeaders_){
00866     param = elems_[h].tag_;
00867     type = elems_[h].type_;
00868     minimum = elems_[h].min_;
00869     maximum = elems_[h].max_;
00870     parents = elems_[h].parents_;
00871     return h++;
00872   }
00873   else{
00874     return -1;
00875   }
00876 }
00877 
00878 void
00879 WsdlInvoker::processResults()
00880 {
00881   try{
00882 
00883     const Message* m = op_->getMessage(WsdlPull::Output);
00884     std::istringstream respstr(results_);
00885     //std::ifstream respstr("r.log");//test
00886     XmlPullParser* xpp = new XmlPullParser(respstr);
00887     xpp->setFeature (FEATURE_PROCESS_NAMESPACES, true);
00888     xpp->require (XmlPullParser::START_DOCUMENT, "", "");
00889 
00890     while (xpp->getEventType () != XmlPullParser::END_DOCUMENT) {
00891 
00892       if (xpp->getEventType () == XmlPullParser::END_DOCUMENT)
00893         break;
00894       
00895       if (xpp->getEventType () == XmlPullParser::END_TAG &&
00896           xpp->getName() == "Envelope" &&
00897           xpp->getNamespace() ==  Soap::soapEnvUri)
00898         break;
00899         
00900       if (xpp->getEventType () != XmlPullParser::START_TAG){
00901         xpp->nextToken ();
00902         continue;
00903       }
00904       
00905       xpp->nextTag ();
00906       Qname elemName (xpp->getName ());
00907       elemName.setNamespace(xpp->getNamespace());
00908       
00909       if (elemName.getNamespace() == Soap::soapEnvUri){
00910         
00911         if (elemName.getLocalName() == "Fault"){
00912           processFault(xpp);
00913           status_ = false;
00914           return;
00915         } 
00916         else if (elemName.getLocalName() == "Header"){
00917 
00918           processHeader(xpp);
00919         }
00920         else if (elemName.getLocalName() == "Body"){
00921 
00922           xpp->nextTag();
00923           processBody(m,xpp);
00924         }
00925         continue; //ignore soap:Body and soap:Envelope tags
00926       }
00927     }
00928     delete xpp;
00929     n_ = oHeaders_;
00930   }
00931   catch (WsdlException we)
00932     {
00933       logger_<<"An Exception occurred ...@"<<we.line
00934              <<":"<<we.col<<std::endl;
00935       logger_<<we.description<<std::endl;
00936       status_ =false;
00937     }
00938   catch (SchemaParserException spe)
00939     {
00940       logger_<<"An Exception occurred ...@"<<spe.line
00941              <<":"<<spe.col<<std::endl;
00942       logger_<<spe.description<<std::endl;
00943       status_ =false;
00944     }
00945   catch (XmlPullParserException xpe)
00946     {
00947       logger_<<"An Exception occurred ...@"<<xpe.line
00948              <<":"<<xpe.col<<std::endl;
00949       logger_<<xpe.description<<std::endl;
00950       status_ =false;
00951     }
00952   return;
00953 }
00954 
00955 WsdlInvoker::~WsdlInvoker()
00956 {
00957   reset();
00958   if (ourParser_){  
00959       delete ourParser_;
00960   }
00961   if (xmlStream_){
00962     
00963     delete xmlStream_;
00964   }
00965   if (soapstr_){
00966     
00967     delete soapstr_;
00968   }
00969 }
00970 
00971 void
00972 WsdlInvoker::reset()
00973 {
00974   n_ =  iHeaders_ = oHeaders_ = 0;
00975   elems_.clear();
00976 
00977   for (size_t x = 0;x<outputs_.size();x++)
00978     delete outputs_[x].second;
00979 
00980   outputs_.clear();
00981   serializeMode_ = false;
00982 }
00983 
00984 bool 
00985 WsdlInvoker::getNextOutput(std::string & name,TypeContainer * & tc)
00986 {
00987   if (status_ && n_ < outputs_.size()){
00988     
00989     name = outputs_[n_].first;
00990     tc = outputs_[n_].second;
00991     n_++;
00992     return true;
00993   }
00994   n_ = oHeaders_;
00995   return false;
00996 }
00997 
00998 
00999 TypeContainer*
01000 WsdlInvoker::getOutput(const std::string  & name)
01001 {
01002   for (unsigned int i = 0 ;status_ && i <outputs_.size();i++){
01003 
01004     if ( name == outputs_[i].first)
01005       return outputs_[i].second;
01006   }
01007   return 0;
01008 }
01009 
01010 bool
01011 WsdlInvoker::getNextHeaderOutput(std::string & name,TypeContainer*& tc)
01012 {
01013   static int j = 0;
01014   if(j<oHeaders_){
01015     name = outputs_[j].first;
01016     tc = outputs_[j].second;
01017     j++;
01018     return true;
01019   }
01020   else{
01021     j = 0;
01022     return false;
01023   }
01024 }
01025 
01026 void * 
01027 WsdlInvoker::getValue(const std::string  & name ,Schema::Type & t)
01028 {
01029   for (unsigned int i = 0 ;status_ && i <outputs_.size();i++){
01030 
01031     if (outputs_[i].second!=0){
01032       outputs_[i].second->rewind();
01033       void * tmp= outputs_[i].second->getValue(name,t);
01034       if (tmp)
01035         return tmp;
01036     }
01037   }
01038   return 0;
01039 }
01040 
01041 
01042 
01043 void
01044 WsdlInvoker::post(long timeout, std::string username, std::string passwd)
01045 {
01046   const std::string  postData = soapstr_->str();
01047   if(verbose_){
01048     
01049     std::ofstream ofs("request.log",std::ios::app);
01050     ofs<<postData;
01051     ofs<<std::endl;
01052     ofs.flush();
01053   }
01054     
01055 #ifdef WITH_CURL
01056   CURL * ctx=0;
01057   CURLcode res;
01058   curl_global_init( CURL_GLOBAL_ALL ) ;
01059   ctx=curl_easy_init();
01060   int bufsize = 0;
01061   if (!ctx)
01062     return ;
01063   curl_easy_setopt( ctx , CURLOPT_URL,  location_.c_str()) ;
01064 
01065   curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , 1 ) ;
01066   if(timeout){
01067     curl_easy_setopt( ctx ,CURLOPT_TIMEOUT, timeout);
01068   }
01069 
01070   if (verbose_) {
01071     curl_easy_setopt( ctx , CURLOPT_VERBOSE,1);
01072     curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , 0 ) ;
01073   }
01074 
01075   curl_easy_setopt( ctx , CURLOPT_POST , 1 );
01076   curl_easy_setopt( ctx , CURLOPT_POSTFIELDS , postData.c_str()) ;
01077   curl_slist* responseHeaders = NULL ;
01078   std::string tmp="SOAPAction: ";
01079   tmp.push_back('"');
01080   tmp+=action_;
01081   tmp.push_back('"');
01082   responseHeaders = curl_slist_append( responseHeaders , tmp.c_str());
01083   responseHeaders = curl_slist_append( responseHeaders ,"Content-Type: text/xml; charset=UTF-8");
01084   responseHeaders = curl_slist_append( responseHeaders ,"Accept: text/xml;");
01085   curl_easy_setopt( ctx , CURLOPT_HTTPHEADER , responseHeaders ) ;
01086   tmp = "wsdlpull";
01087 #ifdef HAVE_CONFIG_H
01088   tmp=tmp+"/"+VERSION;
01089 #endif
01090   curl_easy_setopt( ctx,CURLOPT_USERAGENT,tmp.c_str());
01091   curl_easy_setopt( ctx,CURLOPT_POSTFIELDSIZE,postData.length());
01092   
01093   if (XmlUtils::getProxy()){
01094     curl_easy_setopt(ctx,CURLOPT_PROXY,XmlUtils::getProxyHost().c_str());
01095     tmp=XmlUtils::getProxyUser()+":"+XmlUtils::getProxyPass();
01096     curl_easy_setopt(ctx,CURLOPT_PROXYUSERPWD,tmp.c_str());
01097   }
01098   curl_easy_setopt( ctx ,CURLOPT_WRITEDATA ,&bufsize) ;
01099   curl_easy_setopt( ctx ,CURLOPT_WRITEFUNCTION,storeResults) ;
01100   
01101   // std::logger_ << "- - - BEGIN: response - - -" << std::endl ;
01102   res=curl_easy_perform(ctx);
01103   //  std::logger_ << "- - - END: response - - -" << std::endl ;
01104 
01105   curl_slist_free_all( responseHeaders ) ;
01106   curl_easy_cleanup( ctx ) ;
01107   curl_global_cleanup() ;
01108   
01109 
01110 #elif _WIN32
01111   XmlUtils::winPost(location_,username,passwd,postData,action_,results_);
01112 #endif
01113 
01114   if(verbose_ && results_){
01115     
01116     std::ofstream ofs("response.log",std::ios::app);
01117     ofs<<results_;
01118     ofs<<std::endl;
01119     ofs.flush();
01120   }
01121 
01122 }
01123 
01124 void
01125 WsdlInvoker::printTypeNames(bool f)
01126 {
01127   TypeContainer::printTypeNames_ = false;
01128 }
01129 
01130 
01131 void
01132 WsdlInvoker::processFault(XmlPullParser* xpp)
01133 {
01134 
01135   while (!(xpp->getEventType () == XmlPullParser::END_TAG &&
01136            xpp->getName() == "Fault")) {
01137     
01138     if (xpp->getEventType() == XmlPullParser::START_TAG &&
01139         xpp->getName() == "faultcode"){
01140       
01141       xpp->next();
01142       logger_<<"SOAP Fault Code: "<<xpp->getText()<<std::endl;
01143     }
01144     
01145     if (xpp->getEventType() == XmlPullParser::START_TAG &&
01146         xpp->getName() == "faultstring"){
01147       
01148       xpp->next();
01149       logger_<<"SOAP Fault String: "<<xpp->getText()<<std::endl;
01150     }
01151     if (xpp->getEventType() == XmlPullParser::START_TAG &&
01152         xpp->getName() == "faultactor"){
01153       
01154       xpp->next();
01155       logger_<<"SOAP Fault Actor: "<<xpp->getText()<<std::endl;
01156     }
01157     xpp->next();
01158   }
01159 }
01160 
01161 void 
01162 WsdlInvoker::processBody(const Message* m,
01163                          XmlPullParser* xpp)
01164 {
01165   
01166   if (xpp->getName() == "Fault") {
01167     
01168     processFault(xpp);
01169     status_ = false;
01170     return;
01171   }
01172 
01173   if (style_ == Soap::RPC && use_==Soap::ENCODED){
01174           
01175     if (xpp->getName () == op_->getName()+"Response") {
01176 
01177       //operation's name followed by 'Response' must be the containing element
01178       xpp->nextTag ();
01179       
01180       do {
01181       
01182         if (xpp->getName()=="result"){
01183           xpp->nextText(); //rewind to results
01184           xpp->next();
01185         }
01186         //first look for xsi:type
01187         Qname typ(xpp->getAttributeValue(Schema::SchemaInstaceUri, "type"));
01188         typ.setNamespace(xpp->getNamespace(typ.getPrefix()));
01189         const SchemaParser * sParser = 0;
01190         int typeId = 0;
01191           
01192         if (!(typ.getNamespace() == Soap::soapEncUri &&
01193               typ.getLocalName() == "Array"))//for soap array just use the part's type info
01194           sParser= wParser_->getSchemaParser(typ.getNamespace());
01195           
01196         if (sParser){
01197             
01198           typeId = (const_cast<SchemaParser*>(sParser))->getTypeId(typ);
01199         }
01200         else{
01201 
01202           //if xsi:type doesnt give a clue then see if the part name matches
01203           const Part * p = m->getMessagePart(xpp->getName ());
01204           if (p){
01205             
01206             sParser = wParser_->getSchemaParser(p->schemaId());
01207             typeId = p->type();
01208           }
01209         }
01210         if (sParser && typeId !=0){  
01211             
01212           SchemaValidator * sv= new SchemaValidator(sParser);     
01213           std::string tag = xpp->getName();
01214           TypeContainer * t = sv->validate (xpp, typeId);
01215           outputs_.push_back(std::pair<std::string,TypeContainer*>(tag,t));
01216           xpp->nextTag();
01217           delete sv;
01218         }
01219         else{
01220 
01221           status_ = false;
01222           logger_<<"Unknown Element"<<xpp->getName()<<std::endl;
01223           return;
01224         }
01225       } while (!(xpp->getName() == op_->getName()+"Response" &&
01226                  xpp->getEventType() == XmlPullParser::END_TAG));
01227     }
01228   }
01229   else{
01230     
01231     while (!(xpp->getName() == "Body" && 
01232              xpp->getNamespace() == Soap::soapEnvUri &&
01233              xpp->getEventType() == XmlPullParser::END_TAG)) {
01234              
01235       Qname elemName (xpp->getName ());
01236       elemName.setNamespace(xpp->getNamespace());
01237 
01238       //doc/literal has ref type element in the part
01239       const SchemaParser * sParser =
01240         wParser_->getSchemaParser(elemName.getNamespace());
01241       if (!sParser){
01242           
01243         status_ = false;
01244         logger_<<"Unknown Element"<<elemName<<std::endl;
01245         return;
01246       }
01247       SchemaValidator * sv= new SchemaValidator(sParser);         
01248           
01249       const Element * e = sParser->getElement (elemName);
01250       if(e){
01251         int typeId = e->getType () ;
01252         TypeContainer * t = sv->validate (xpp, typeId);
01253         std::pair<std::string,TypeContainer*> pr(elemName.getLocalName(),t);
01254         outputs_.push_back(pr);
01255       }
01256       else{
01257         status_ = false;
01258         std::cerr<<"Unkown element "<<elemName.getLocalName()<<std::endl;
01259         return;
01260       }
01261       delete sv;
01262       xpp->nextTag();
01263     }
01264   }
01265   status_ = true;
01266 }
01267 
01268 void
01269 WsdlInvoker::processHeader(XmlPullParser *xpp)
01270 {
01271   Qname elem;
01272   const SchemaParser * sParser = 0;
01273   int type;
01274   xpp->nextTag ();
01275   std::string tag = xpp->getName();
01276 
01277   while (!(xpp->getEventType() == XmlPullParser::END_TAG &&
01278            xpp->getName() == "Header")){
01279 
01280 
01281     //first look for xsi:type
01282     if (xpp->getAttributeValue(Schema::SchemaInstaceUri, "type") != "" ) {
01283       
01284       elem = Qname(xpp->getAttributeValue(Schema::SchemaInstaceUri, "type"));
01285       elem.setNamespace(xpp->getNamespace(elem.getPrefix()));
01286       sParser= wParser_->getSchemaParser(elem.getNamespace());
01287       type = (const_cast<SchemaParser*>(sParser))->getTypeId(elem);  
01288     }
01289     else {
01290 
01291       elem = Qname(xpp->getName());
01292       elem.setNamespace(xpp->getNamespace());      
01293       sParser=wParser_->getSchemaParser(elem.getNamespace());
01294       const Element * e = sParser->getElement (elem);
01295       if(e){
01296         type = e->getType ();
01297       }
01298     }
01299     SchemaValidator * sv= new SchemaValidator(sParser);   
01300     TypeContainer * t = sv->validate (xpp, type);
01301     outputs_.push_back(std::pair<std::string,TypeContainer*>(tag,t));
01302     oHeaders_++; 
01303     xpp->nextTag();
01304     delete sv;
01305   }
01306   xpp->nextTag();   
01307 }
01308 
01309 bool
01310 WsdlInvoker::isSoapArray (const ComplexType * ct,
01311                           const SchemaParser * sParser)
01312 {
01313   const XSDType * baseType=sParser->getType(ct->getBaseTypeId());
01314   if (baseType) {
01315     if(baseType->getNamespace()==Soap::soapEncUri &&
01316        baseType->getName()=="Array")
01317       return true;
01318   }
01319   return false;
01320 }
01321 
01322 void
01323 WsdlInvoker::setCredentials(const std::string & user, const std::string & pass)
01324 {
01325   username_ = user;
01326   password_ = pass;
01327   XmlUtils::setProxyUser(user);
01328   XmlUtils::setProxyPass(pass);
01329   XmlUtils::setProxy(true);
01330 }
01331 
01332 void
01333 WsdlInvoker::setProxy(const std::string & host,int  port)
01334 {
01335   host_ = host;
01336   port_ = port;
01337   std::ostringstream oss;
01338   oss<<host<<":"<<port;
01339   XmlUtils::setProxyHost(oss.str());
01340   XmlUtils::setProxy(true);
01341 }
01342 
01343 
01344 }
01345 
01346 size_t
01347 storeResults(void * buf,size_t sz,size_t nmemb,void* userdata)
01348 {
01349   int *bufsize= (int*)userdata;
01350   if (results_ == 0){
01351     
01352     results_ = (char*)malloc(sizeof(char) * sz * nmemb);
01353   }
01354   else{
01355     results_ = (char*) realloc(results_,sizeof(char) * sz * nmemb+ (*bufsize));
01356   }
01357   memcpy (results_+(*bufsize),buf,sz*nmemb);
01358   *bufsize+=sz*nmemb;
01359   return sz*nmemb;
01360 }

Generated on Sun Nov 26 03:04:43 2006 for wsdlpull by  doxygen 1.4.6