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

Generated on Fri Oct 19 19:34:05 2007 for wsdlpull by  doxygen 1.4.6