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   const XSDType * pType = sParser->getType(typeId);
00355   if ( pType== 0 ||
00356        pType->isSimple() ||
00357        pType->getContentModel() == Schema::Simple){
00358     
00359     if (serializeMode_ == false){
00360       
00361       parents.push_back(tag);
00362       Parameter p(typeId,t,minimum,maximum,sParser,parents);
00363       elems_.push_back(p);
00364 
00365 #ifdef LOGGING
00366 
00367       std::cout<<"Adding input type "<<tag<<XmlUtils::dbsp
00368                <<sParser->getTypeName(typeId)<<XmlUtils::dbsp;
00369       std::cout<<sParser->getNamespace()<<std::endl;
00370 #endif
00371     }
00372     else{
00373       //generate the xml
00374       serializeParam(n_++,t,sParser);
00375     }
00376   }
00377   else{
00378 
00379     if (serializeMode_){
00380       
00381       if (style_ == Soap::DOC){
00382     
00383         xmlStream_->setPrefix("s",sParser->getNamespace());
00384         xmlStream_->startTag(sParser->getNamespace(),t);
00385       }
00386       else{
00387 
00388         xmlStream_->startTag("",t);
00389 
00390         //fix for sending SOAP arrays.add the soap arrayType attribute
00391         //works only for 1-D arrays
00392         const ComplexType* ct = static_cast<const ComplexType*>(pType);
00393         if(isSoapArray(ct,sParser)){
00394 
00395           std::string arrayName = ct->getName();
00396           arrayName = "ns:"+arrayName+"[1]";
00397           xmlStream_->attribute(Soap::soapEncUri,"arrayType",arrayName);
00398         }
00399       }
00400     }
00401     
00402     const ComplexType * ct =
00403       static_cast<const ComplexType*>(pType);
00404     
00405     //complex types handling
00406     if (ct->getNumAttributes() > 0) {
00407       
00408       for (int i = 0; i < ct->getNumAttributes(); i++) {
00409           
00410         const Attribute*at = ct->getAttribute(i);
00411         /*
00412          * Check for the correctness of each attribute
00413          */
00414         if (at->isRequired()){
00415         
00416           if (serializeMode_ == false){
00417 
00418             std::vector<std::string> attparents(parents);
00419             attparents.push_back(tag);
00420             attparents.push_back("#" + at->getName() + "#");
00421             Parameter p((Schema::Type)at->getType(),at->getName(),elems_.size(),0,sParser,
00422                         attparents);
00423             elems_.push_back(p);
00424           }
00425           else{
00426             //generate the xml
00427             
00428             xmlStream_->attribute(sParser->getNamespace(),at->getName(),elems_[n_++].data_[0]);
00429           }
00430         }
00431         else
00432           continue;
00433       }
00434     }
00435   
00436     if (ct->getContentModel() == Schema::Simple) {
00437 
00438       if (serializeMode_ == false){
00439       
00440         parents.push_back(tag);
00441         Parameter p((Schema::Type)ct->getContentType(),tag,minimum,maximum,sParser,parents);
00442         elems_.push_back(p);
00443       }
00444       else{
00445         //generate the xml
00446         serializeParam(n_++,t,sParser);
00447       }
00448     }
00449     else{
00450           
00451       ContentModel* cm=ct->getContents();
00452       if(cm){
00453 
00454         parents.push_back(tag);
00455         serializeContentModel(cm,sParser,parents);
00456       }
00457     }
00458 
00459     if (serializeMode_){
00460 
00461       if (style_ == Soap::DOC){
00462     
00463         xmlStream_->endTag(sParser->getNamespace(),tag);
00464       }
00465       else{
00466         
00467         xmlStream_->endTag("",t);
00468       }
00469     }
00470   }
00471 }
00472 
00473 void
00474 WsdlInvoker::serializeContentModel(ContentModel *cm,
00475                                    const SchemaParser *sParser,
00476                                    std::vector<std::string> parents)
00477 {
00478   
00479   ContentModel::ContentsIterator cit_b=cm->begin();
00480   ContentModel::ContentsIterator cit_e=cm->end();
00481   ContentModel::ContentsIterator ci=cit_b;
00482 
00483   switch (cm->getCompositor())
00484     {
00485     case Schema::All:
00486     case Schema::Sequence:
00487     case Schema::Choice:
00488       {
00489         // a simple logic to start with
00490         // not taking care of all,choice ,sequence as of now
00491         
00492         for (ci=cit_b;ci!=cit_e;ci++){
00493           
00494           if(ci->second==ContentModel::Particle &&
00495              ci->first.e->getMax() > 0){
00496 
00497             const SchemaParser* s1Parser = sParser;
00498             Schema::Type t=(Schema::Type)ci->first.e->getType();
00499             
00500             if (!ci->first.e->getTypeNamespace().empty() &&
00501                 sParser->isImported(ci->first.e->getTypeNamespace()) &&
00502                 sParser->getNamespace() != ci->first.e->getTypeNamespace()) {
00503         
00504               //here the type of the element is defined in another imported schemaparser
00505               //so try to get the pointer.
00506               t = (Schema::Type)sParser->getType(t)->getTypeId();
00507               sParser = sParser->getImportedSchemaParser(ci->first.e->getTypeNamespace());
00508             }
00509            
00510             serializeType(t,
00511                           ci->first.e->getName(),
00512                           sParser,
00513                           ci->first.e->getMin(),
00514                           ci->first.e->getMax(),
00515                           parents);
00516             sParser = s1Parser;
00517           }
00518           else if (ci->second==ContentModel::Container) {
00519             
00520             //nested xsd:sequence inside choice..nested content models
00521             serializeContentModel(ci->first.c,
00522                                   sParser,
00523                                   parents);
00524               
00525           }
00526           else if (ci->second==ContentModel::ParticleGroup){
00527             
00528             //xsd:group inside 
00529             serializeContentModel(ci->first.g->getContents(),
00530                                   sParser,
00531                                   parents);
00532           }
00533         }
00534         break;
00535       }
00536     }
00537 }
00538 
00539 
00540 void
00541 WsdlInvoker::serializeParam(int n,const std::string & tag,
00542                             const SchemaParser * sParser)
00543 {
00544 
00545   std::string t=tag;
00546   if (tag=="*")
00547     t="item";
00548     
00549   for (int i = 0 ;i<elems_[n].n_;i++){
00550 
00551     if (style_ == Soap::DOC){
00552     
00553       xmlStream_->setPrefix("s",sParser->getNamespace());
00554       xmlStream_->startTag(sParser->getNamespace(),t);
00555     }
00556     else{
00557       
00558         xmlStream_->startTag("",t);
00559 
00560       //xsi::type is needed for many SOAP servers
00561       if (sParser->isBasicType(elems_[n].type_)){
00562 
00563         xmlStream_->attribute(Schema::SchemaInstaceUri,
00564                               "type",
00565                               "xsd:"+sParser->getTypeName(elems_[n].type_));
00566       }
00567     }
00568     
00569     xmlStream_->text(elems_[n].data_[i]);
00570         
00571     if (style_ == Soap::DOC){
00572     
00573       xmlStream_->endTag(sParser->getNamespace(),t);
00574     }
00575     else{
00576 
00577       xmlStream_->endTag("",t);
00578     }
00579   }
00580 }
00581 
00582 
00583 bool
00584 WsdlInvoker::setInputValue(const int param,void** values,unsigned int occurs)
00585 {
00586 
00587   if (occurs < elems_[param].min_ ||
00588       occurs > elems_[param].max_)
00589     return false;
00590 
00591   SchemaValidator *sv = new SchemaValidator (elems_[param].sParser_);
00592   for (unsigned int i = 0 ;i < occurs ;i++){
00593       
00594     TypeContainer * tc = sv->validate(values[i],
00595                                       elems_[param].type_);
00596     if (!tc->isValueValid()){
00597         
00598       return false;
00599     }
00600     std::ostringstream oss;
00601     tc->print(oss);
00602     elems_[param].data_.push_back(oss.str());
00603     delete tc;
00604   }
00605   delete sv;
00606   
00607   elems_[param].n_ = occurs;
00608   return true;
00609 }
00610 
00611 bool
00612 WsdlInvoker::setInputValue(const int param,std::vector<std::string> values)
00613 {
00614 
00615 
00616   if (values.size() < elems_[param].min_ ||
00617       values.size() > elems_[param].max_)
00618     return false;
00619 
00620   SchemaValidator *sv = new SchemaValidator (elems_[param].sParser_);
00621   
00622   for (size_t i = 0 ;i < values.size() ;i++){
00623       
00624     TypeContainer * tc = sv->validate(values[i],
00625                                       elems_[param].type_);
00626     if (!tc->isValueValid()){
00627         
00628       return false;
00629     }
00630     elems_[param].data_.push_back(values[i]);
00631     delete tc;
00632   }
00633   delete sv;
00634   
00635   elems_[param].n_ = values.size();
00636   return true;
00637 }
00638 
00639 bool
00640 WsdlInvoker::setInputValue(const int param,std::string val)
00641 {
00642 
00643   const SchemaParser* sParser = elems_[param].sParser_;
00644   SchemaValidator *sv = new SchemaValidator (sParser);
00645   Schema::Type t = elems_[param].type_;
00646   const XSDType * pType = sParser->getType(t);
00647   if (pType && !pType->isSimple()){
00648 
00649     if (pType->getContentModel() != Schema::Simple)
00650       return false;
00651 
00652     const ComplexType * ct = static_cast<const ComplexType*>(pType);
00653     t = (Schema::Type)ct->getContentType();
00654   }
00655   
00656   TypeContainer * tc = sv->validate(val,t);
00657   if (!(tc && tc->isValueValid())){
00658         
00659     return false;
00660   }
00661   if (elems_[param].data_.size() == 0)
00662     elems_[param].data_.push_back(val);
00663   else
00664     elems_[param].data_[0]=val;
00665 
00666   delete tc;
00667     
00668   delete sv;
00669   
00670   elems_[param].n_ = 1;
00671   return true;
00672 }
00673 
00674 
00675 
00676 bool
00677 WsdlInvoker::setInputValue(const int param,void* val)
00678 {
00679 
00680   const SchemaParser*  sParser = elems_[param].sParser_;
00681   SchemaValidator *sv = new SchemaValidator (sParser);
00682   Schema::Type t = elems_[param].type_;
00683   const XSDType * pType = sParser->getType(t);
00684   if (pType && !pType->isSimple()){
00685 
00686     if (pType->getContentModel() != Schema::Simple)
00687       return false;
00688 
00689     const ComplexType * ct = static_cast<const ComplexType*>(pType);
00690     t = (Schema::Type)ct->getContentType();
00691   }
00692 
00693   TypeContainer * tc = sv->validate(val,t);
00694   if (!(tc && tc->isValueValid())){
00695         
00696     return false;
00697   }
00698   std::ostringstream oss;
00699   tc->print(oss);
00700   if (elems_[param].data_.size() == 0)
00701     elems_[param].data_.push_back(oss.str());
00702   else
00703     elems_[param].data_[0]=oss.str();
00704   delete tc;
00705   delete sv;
00706   elems_[param].n_ = 1;
00707   return true;
00708 }
00709 
00710 bool
00711 WsdlInvoker::setValue(const std::string & param,void* val)
00712 {
00713   for (size_t s = 0;s<elems_.size();s++){
00714     
00715     if (elems_[s].tag_ == param)
00716       return setInputValue(s,val);
00717   }
00718   return false;
00719 }
00720 
00721 bool
00722 WsdlInvoker::setValue(const std::string & param,void** values,unsigned int occur)
00723 {
00724 
00725   for (size_t s = 0;s<elems_.size();s++){
00726     
00727     if (elems_[s].tag_ == param)
00728       return setInputValue(s,values,occur);
00729   }
00730   return false;
00731 }
00732  
00733 bool
00734 WsdlInvoker::setValue(const std::string & param,std::string val)
00735 {
00736   for (size_t s = 0;s<elems_.size();s++){
00737     
00738     if (elems_[s].tag_ == param)
00739       return setInputValue(s,val);
00740   }
00741   return false;
00742 }
00743 
00744 bool
00745 WsdlInvoker::setValue(const std::string & param,std::vector<std::string> values)
00746 {
00747   for (size_t s = 0;s<elems_.size();s++){
00748     
00749     if (elems_[s].tag_ == param)
00750       return setInputValue(s,values);
00751   }
00752   return false;
00753 }
00754 
00755 
00756 std::string
00757 WsdlInvoker::getSoapMessage(){
00758 
00759   dontPost_ = true;
00760   invoke();
00761   return soapstr_->str();
00762 }
00763 
00764 
00765 
00766 bool
00767 WsdlInvoker::invoke(long timeout)
00768 {
00769 
00770   if (xmlStream_){
00771     
00772     delete xmlStream_;
00773   }
00774   if (soapstr_){
00775     
00776     delete soapstr_;
00777   }
00778   if (results_){
00779     delete results_;
00780     results_ = 0;
00781   }
00782 
00783   for (size_t x = 0;x<outputs_.size();x++)
00784     delete outputs_[x].second;
00785 
00786   outputs_.clear();
00787 
00788   soapstr_ = new std::ostringstream();
00789   xmlStream_ = new XmlSerializer(*soapstr_);
00790 
00791   serializeMode_ = true;
00792   xmlStream_->setPrefix("ns",nsp_);
00793   xmlStream_->startDocument("UTF-8",false);
00794   xmlStream_->setPrefix("SOAP-ENV",Soap::soapEnvUri);
00795   xmlStream_->setPrefix("SOAP-ENC",Soap::soapEncUri);
00796   xmlStream_->setPrefix("xsd",Schema::SchemaUri);
00797   xmlStream_->setPrefix("xsi",Schema::SchemaInstaceUri);
00798   xmlStream_->startTag(Soap::soapEnvUri,"Envelope");
00799   
00800   if (style_ == Soap::RPC) {
00801     
00802     xmlStream_->attribute(Soap::soapEnvUri,
00803                           "encodingStyle",
00804                           Soap::soapEncUri);
00805   }
00806 
00807   n_ = 0;
00808   if (hMessage_){
00809     xmlStream_->startTag(Soap::soapEnvUri,"Header");
00810     serializeHeader();
00811     xmlStream_->endTag(Soap::soapEnvUri,"Header");
00812   }
00813 
00814   xmlStream_->startTag(Soap::soapEnvUri,"Body");
00815   if (style_ == Soap::RPC){
00816     
00817     xmlStream_->startTag(nsp_,op_->getName());
00818   }
00819 
00820   serialize();
00821   if (style_ == Soap::RPC){
00822     xmlStream_->endTag(nsp_,op_->getName());
00823   }
00824 
00825   xmlStream_->endTag(Soap::soapEnvUri,"Body");
00826   xmlStream_->endTag(Soap::soapEnvUri,"Envelope");
00827   xmlStream_->flush();
00828   
00829 
00830 
00831   //test
00832   //  status_ = true;
00833   //    processResults();
00834   //    return status_;
00835   //test
00836   if (dontPost_)
00837     return true;
00838 
00839   post(timeout);
00840   if (results_){
00841     processResults();
00842     if (status_)
00843       return true;
00844   }
00845   else{
00846     
00847     logger_<<"Couldnt connect to "<<location_;
00848   }
00849     
00850   return false;
00851 }
00852 
00853 int
00854 WsdlInvoker::getNextInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum)
00855 {
00856   std::vector<std::string> parents;
00857   return getNextInput(param, type, minimum, maximum, parents);
00858 }
00859 
00860 int
00861 WsdlInvoker::getNextInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum,
00862                           std::vector<std::string> & parents)
00863 {
00864   if (n_ < elems_.size()){
00865     
00866     param = elems_[n_].tag_;
00867     type = elems_[n_].type_;
00868     minimum = elems_[n_].min_;
00869     parents = elems_[n_].parents_;
00870     maximum = elems_[n_].max_;
00871     return n_++;
00872   }
00873   else{
00874     return -1;
00875   }
00876 }
00877 
00878 int
00879 WsdlInvoker::getNextHeaderInput(std::string & param ,Schema::Type & type,
00880                                 int & minimum,int & maximum)
00881 {
00882 
00883   std::vector<std::string> parents;
00884   return getNextHeaderInput(param,type,minimum,maximum,parents);
00885 }
00886 
00887 int
00888 WsdlInvoker::getNextHeaderInput(std::string & param ,Schema::Type & type,
00889                                 int & minimum,int & maximum,
00890                                 std::vector<std::string> & parents)
00891 {
00892   static int  h=0;
00893   if (h<iHeaders_){
00894     param = elems_[h].tag_;
00895     type = elems_[h].type_;
00896     minimum = elems_[h].min_;
00897     maximum = elems_[h].max_;
00898     parents = elems_[h].parents_;
00899     return h++;
00900   }
00901   else{
00902     return -1;
00903   }
00904 }
00905 
00906 void
00907 WsdlInvoker::processResults()
00908 {
00909   try{
00910 
00911     const Message* m = op_->getMessage(WsdlPull::Output);
00912     std::istringstream respstr(results_);
00913         //std::ifstream respstr("r.log");//test
00914     XmlPullParser* xpp = new XmlPullParser(respstr);
00915     xpp->setFeature (FEATURE_PROCESS_NAMESPACES, true);
00916     xpp->require (XmlPullParser::START_DOCUMENT, "", "");
00917 
00918     while (xpp->getEventType () != XmlPullParser::END_DOCUMENT) {
00919 
00920       if (xpp->getEventType () == XmlPullParser::END_DOCUMENT)
00921         break;
00922       
00923       if (xpp->getEventType () == XmlPullParser::END_TAG &&
00924           xpp->getName() == "Envelope" &&
00925           xpp->getNamespace() ==  Soap::soapEnvUri)
00926         break;
00927         
00928       if (xpp->getEventType () != XmlPullParser::START_TAG){
00929         xpp->nextToken ();
00930         continue;
00931       }
00932       
00933       xpp->nextTag ();
00934       Qname elemName (xpp->getName ());
00935       elemName.setNamespace(xpp->getNamespace());
00936       
00937       if (elemName.getNamespace() == Soap::soapEnvUri){
00938         
00939         if (elemName.getLocalName() == "Fault"){
00940           processFault(xpp);
00941           status_ = false;
00942           return;
00943         } 
00944         else if (elemName.getLocalName() == "Header"){
00945 
00946           processHeader(xpp);
00947         }
00948         else if (elemName.getLocalName() == "Body"){
00949 
00950           xpp->nextTag();
00951           processBody(m,xpp);
00952         }
00953         continue; //ignore soap:Body and soap:Envelope tags
00954       }
00955     }
00956     delete xpp;
00957     n_ = oHeaders_;
00958   }
00959   catch (WsdlException we)
00960     {
00961       logger_<<"An Exception occurred ...@"<<we.line
00962              <<":"<<we.col<<std::endl;
00963       logger_<<we.description<<std::endl;
00964       status_ =false;
00965     }
00966   catch (SchemaParserException spe)
00967     {
00968       logger_<<"An Exception occurred ...@"<<spe.line
00969              <<":"<<spe.col<<std::endl;
00970       logger_<<spe.description<<std::endl;
00971       status_ =false;
00972     }
00973   catch (XmlPullParserException xpe)
00974     {
00975       logger_<<"An Exception occurred ...@"<<xpe.line
00976              <<":"<<xpe.col<<std::endl;
00977       logger_<<xpe.description<<std::endl;
00978       status_ =false;
00979     }
00980   return;
00981 }
00982 
00983 WsdlInvoker::~WsdlInvoker()
00984 {
00985   reset();
00986   if (ourParser_){  
00987       delete ourParser_;
00988   }
00989   if (xmlStream_){
00990     
00991     delete xmlStream_;
00992   }
00993   if (soapstr_){
00994     
00995     delete soapstr_;
00996   }
00997 }
00998 
00999 void
01000 WsdlInvoker::reset()
01001 {
01002   n_ =  iHeaders_ = oHeaders_ = 0;
01003   elems_.clear();
01004 
01005   for (size_t x = 0;x<outputs_.size();x++)
01006     delete outputs_[x].second;
01007 
01008   outputs_.clear();
01009   serializeMode_ = false;
01010 }
01011 
01012 bool 
01013 WsdlInvoker::getNextOutput(std::string & name,TypeContainer * & tc)
01014 {
01015   if (status_ && n_ < outputs_.size()){
01016     
01017     name = outputs_[n_].first;
01018     tc = outputs_[n_].second;
01019     n_++;
01020     return true;
01021   }
01022   n_ = oHeaders_;
01023   return false;
01024 }
01025 
01026 
01027 TypeContainer*
01028 WsdlInvoker::getOutput(const std::string  & name)
01029 {
01030   for (unsigned int i = 0 ;status_ && i <outputs_.size();i++){
01031 
01032     if ( name == outputs_[i].first)
01033       return outputs_[i].second;
01034   }
01035   return 0;
01036 }
01037 
01038 bool
01039 WsdlInvoker::getNextHeaderOutput(std::string & name,TypeContainer*& tc)
01040 {
01041   static int j = 0;
01042   if(j<oHeaders_){
01043     name = outputs_[j].first;
01044     tc = outputs_[j].second;
01045     j++;
01046     return true;
01047   }
01048   else{
01049     j = 0;
01050     return false;
01051   }
01052 }
01053 
01054 void * 
01055 WsdlInvoker::getValue(const std::string  & name ,Schema::Type & t)
01056 {
01057   for (unsigned int i = 0 ;status_ && i <outputs_.size();i++){
01058 
01059     if (outputs_[i].second!=0){
01060       outputs_[i].second->rewind();
01061       void * tmp= outputs_[i].second->getValue(name,t);
01062       if (tmp)
01063         return tmp;
01064     }
01065   }
01066   return 0;
01067 }
01068 
01069 
01070 
01071 void
01072 WsdlInvoker::post(long timeout, std::string username, std::string passwd)
01073 {
01074   const std::string  postData = soapstr_->str();
01075   if(verbose_){
01076     
01077     std::ofstream ofs("request.log",std::ios::app);
01078     ofs<<postData;
01079     ofs<<std::endl;
01080     ofs.flush();
01081   }
01082     
01083 #ifdef WITH_CURL
01084   CURL * ctx=0;
01085   CURLcode res;
01086   curl_global_init( CURL_GLOBAL_ALL ) ;
01087   ctx=curl_easy_init();
01088   int bufsize = 0;
01089   if (!ctx)
01090     return ;
01091   curl_easy_setopt( ctx , CURLOPT_URL,  location_.c_str()) ;
01092 
01093   curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , 1 ) ;
01094   if(timeout){
01095     curl_easy_setopt( ctx ,CURLOPT_TIMEOUT, timeout);
01096   }
01097 
01098   if (verbose_) {
01099     curl_easy_setopt( ctx , CURLOPT_VERBOSE,1);
01100     curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , 0 ) ;
01101   }
01102 
01103   curl_easy_setopt( ctx , CURLOPT_POST , 1 );
01104   curl_easy_setopt( ctx , CURLOPT_POSTFIELDS , postData.c_str()) ;
01105   curl_slist* responseHeaders = NULL ;
01106   std::string tmp="SOAPAction: ";
01107   tmp.push_back('"');
01108   tmp+=action_;
01109   tmp.push_back('"');
01110   responseHeaders = curl_slist_append( responseHeaders , tmp.c_str());
01111   responseHeaders = curl_slist_append( responseHeaders ,"Content-Type: text/xml; charset=UTF-8");
01112   responseHeaders = curl_slist_append( responseHeaders ,"Accept: text/xml;");
01113   curl_easy_setopt( ctx , CURLOPT_HTTPHEADER , responseHeaders ) ;
01114   tmp = "wsdlpull";
01115 #ifdef HAVE_CONFIG_H
01116   tmp=tmp+"/"+VERSION;
01117 #endif
01118   curl_easy_setopt( ctx,CURLOPT_USERAGENT,tmp.c_str());
01119   curl_easy_setopt( ctx,CURLOPT_POSTFIELDSIZE,postData.length());
01120   
01121   if (XmlUtils::getProxy()){
01122     curl_easy_setopt(ctx,CURLOPT_PROXY,XmlUtils::getProxyHost().c_str());
01123     tmp=XmlUtils::getProxyUser()+":"+XmlUtils::getProxyPass();
01124     curl_easy_setopt(ctx,CURLOPT_PROXYUSERPWD,tmp.c_str());
01125   }
01126   curl_easy_setopt( ctx ,CURLOPT_WRITEDATA ,&bufsize) ;
01127   curl_easy_setopt( ctx ,CURLOPT_WRITEFUNCTION,storeResults) ;
01128   
01129   // std::logger_ << "- - - BEGIN: response - - -" << std::endl ;
01130   res=curl_easy_perform(ctx);
01131   //  std::logger_ << "- - - END: response - - -" << std::endl ;
01132 
01133   curl_slist_free_all( responseHeaders ) ;
01134   curl_easy_cleanup( ctx ) ;
01135   curl_global_cleanup() ;
01136   
01137 
01138 #elif _WIN32
01139   XmlUtils::winPost(location_,username,passwd,postData,action_,results_);
01140 #endif
01141 
01142   if(verbose_ && results_){
01143     
01144     std::ofstream ofs("response.log",std::ios::app);
01145     ofs<<results_;
01146     ofs<<std::endl;
01147     ofs.flush();
01148   }
01149 
01150 }
01151 
01152 void
01153 WsdlInvoker::printTypeNames(bool f)
01154 {
01155   TypeContainer::printTypeNames_ = false;
01156 }
01157 
01158 
01159 void
01160 WsdlInvoker::processFault(XmlPullParser* xpp)
01161 {
01162 
01163   while (!(xpp->getEventType () == XmlPullParser::END_TAG &&
01164            xpp->getName() == "Fault")) {
01165     
01166     if (xpp->getEventType() == XmlPullParser::START_TAG &&
01167         xpp->getName() == "faultcode"){
01168       
01169       xpp->next();
01170       logger_<<"SOAP Fault Code: "<<xpp->getText()<<std::endl;
01171     }
01172     
01173     if (xpp->getEventType() == XmlPullParser::START_TAG &&
01174         xpp->getName() == "faultstring"){
01175       
01176       xpp->next();
01177       logger_<<"SOAP Fault String: "<<xpp->getText()<<std::endl;
01178     }
01179     if (xpp->getEventType() == XmlPullParser::START_TAG &&
01180         xpp->getName() == "faultactor"){
01181       
01182       xpp->next();
01183       logger_<<"SOAP Fault Actor: "<<xpp->getText()<<std::endl;
01184     }
01185     xpp->next();
01186   }
01187 }
01188 
01189 void 
01190 WsdlInvoker::processBody(const Message* m,
01191                          XmlPullParser* xpp)
01192 {
01193   
01194   if (xpp->getName() == "Fault") {
01195     
01196     processFault(xpp);
01197     status_ = false;
01198     return;
01199   }
01200 
01201   if (style_ == Soap::RPC && use_==Soap::ENCODED){
01202           
01203     if (xpp->getName () == op_->getName()+"Response") {
01204 
01205       //operation's name followed by 'Response' must be the containing element
01206       xpp->nextTag ();
01207       
01208       do {
01209       
01210         if (xpp->getName()=="result"){
01211           xpp->nextText(); //rewind to results
01212           xpp->next();
01213         }
01214         //first look for xsi:type
01215         Qname typ(xpp->getAttributeValue(Schema::SchemaInstaceUri, "type"));
01216         typ.setNamespace(xpp->getNamespace(typ.getPrefix()));
01217         const SchemaParser * sParser = 0;
01218         int typeId = 0;
01219           
01220         if (!(typ.getNamespace() == Soap::soapEncUri &&
01221               typ.getLocalName() == "Array"))//for soap array just use the part's type info
01222           sParser= wParser_->getSchemaParser(typ.getNamespace());
01223           
01224         if (sParser){
01225             
01226           typeId = (const_cast<SchemaParser*>(sParser))->getTypeId(typ);
01227         }
01228         else{
01229 
01230           //if xsi:type doesnt give a clue then see if the part name matches
01231           const Part * p = m->getMessagePart(xpp->getName ());
01232           if (p){
01233             
01234             sParser = wParser_->getSchemaParser(p->schemaId());
01235             typeId = p->type();
01236           }
01237         }
01238         if (sParser && typeId !=0){  
01239             
01240           SchemaValidator * sv= new SchemaValidator(sParser);     
01241           std::string tag = xpp->getName();
01242           TypeContainer * t = sv->validate (xpp, typeId);
01243           outputs_.push_back(std::pair<std::string,TypeContainer*>(tag,t));
01244           xpp->nextTag();
01245           delete sv;
01246         }
01247         else{
01248 
01249           status_ = false;
01250           logger_<<"Unknown Element"<<xpp->getName()<<std::endl;
01251           return;
01252         }
01253       } while (!(xpp->getName() == op_->getName()+"Response" &&
01254                  xpp->getEventType() == XmlPullParser::END_TAG));
01255     }
01256   }
01257   else{
01258     
01259     while (!(xpp->getName() == "Body" && 
01260              xpp->getNamespace() == Soap::soapEnvUri &&
01261              xpp->getEventType() == XmlPullParser::END_TAG)) {
01262              
01263       Qname elemName (xpp->getName ());
01264       elemName.setNamespace(xpp->getNamespace());
01265 
01266       //doc/literal has ref type element in the part
01267       const SchemaParser * sParser =
01268         wParser_->getSchemaParser(elemName.getNamespace());
01269       if (!sParser){
01270           
01271         status_ = false;
01272         logger_<<"Unknown Element"<<elemName<<std::endl;
01273         return;
01274       }
01275       SchemaValidator * sv= new SchemaValidator(sParser);         
01276           
01277       const Element * e = sParser->getElement (elemName);
01278       if(e){
01279         int typeId = e->getType () ;
01280         TypeContainer * t = sv->validate (xpp, typeId);
01281         std::pair<std::string,TypeContainer*> pr(elemName.getLocalName(),t);
01282         outputs_.push_back(pr);
01283       }
01284       else{
01285         status_ = false;
01286         std::cerr<<"Unkown element "<<elemName.getLocalName()<<std::endl;
01287         return;
01288       }
01289       delete sv;
01290       xpp->nextTag();
01291     }
01292   }
01293   status_ = true;
01294 }
01295 
01296 void
01297 WsdlInvoker::processHeader(XmlPullParser *xpp)
01298 {
01299   Qname elem;
01300   const SchemaParser * sParser = 0;
01301   int type;
01302   xpp->nextTag ();
01303   std::string tag = xpp->getName();
01304 
01305   while (!(xpp->getEventType() == XmlPullParser::END_TAG &&
01306            xpp->getName() == "Header")){
01307 
01308 
01309     //first look for xsi:type
01310     if (xpp->getAttributeValue(Schema::SchemaInstaceUri, "type") != "" ) {
01311       
01312       elem = Qname(xpp->getAttributeValue(Schema::SchemaInstaceUri, "type"));
01313       elem.setNamespace(xpp->getNamespace(elem.getPrefix()));
01314       sParser= wParser_->getSchemaParser(elem.getNamespace());
01315       type = (const_cast<SchemaParser*>(sParser))->getTypeId(elem);  
01316     }
01317     else {
01318 
01319       elem = Qname(xpp->getName());
01320       elem.setNamespace(xpp->getNamespace());      
01321       sParser=wParser_->getSchemaParser(elem.getNamespace());
01322       const Element * e = sParser->getElement (elem);
01323       if(e){
01324         type = e->getType ();
01325       }
01326     }
01327     SchemaValidator * sv= new SchemaValidator(sParser);   
01328     TypeContainer * t = sv->validate (xpp, type);
01329     outputs_.push_back(std::pair<std::string,TypeContainer*>(tag,t));
01330     oHeaders_++; 
01331     xpp->nextTag();
01332     delete sv;
01333   }
01334   xpp->nextTag();   
01335 }
01336 
01337 bool
01338 WsdlInvoker::isSoapArray (const ComplexType * ct,
01339                           const SchemaParser * sParser)
01340 {
01341   const XSDType * baseType=sParser->getType(ct->getBaseTypeId());
01342   if (baseType) {
01343     if(baseType->getNamespace()==Soap::soapEncUri &&
01344        baseType->getName()=="Array")
01345       return true;
01346   }
01347   return false;
01348 }
01349 
01350 void
01351 WsdlInvoker::setCredentials(const std::string & user, const std::string & pass)
01352 {
01353   username_ = user;
01354   password_ = pass;
01355   XmlUtils::setProxyUser(user);
01356   XmlUtils::setProxyPass(pass);
01357   XmlUtils::setProxy(true);
01358 }
01359 
01360 void
01361 WsdlInvoker::setProxy(const std::string & host,int  port)
01362 {
01363   host_ = host;
01364   port_ = port;
01365   std::ostringstream oss;
01366   oss<<host<<":"<<port;
01367   XmlUtils::setProxyHost(oss.str());
01368   XmlUtils::setProxy(true);
01369 }
01370 
01371 
01372 }
01373 
01374 size_t
01375 storeResults(void * buf,size_t sz,size_t nmemb,void* userdata)
01376 {
01377   int *bufsize= (int*)userdata;
01378   if (results_ == 0){
01379     
01380     results_ = (char*)malloc(sizeof(char) * sz * nmemb);
01381   }
01382   else{
01383     results_ = (char*) realloc(results_,sizeof(char) * sz * nmemb+ (*bufsize));
01384   }
01385   memcpy (results_+(*bufsize),buf,sz*nmemb);
01386   *bufsize+=sz*nmemb;
01387   return sz*nmemb;
01388 }

Generated on Sun Aug 5 20:01:34 2007 for wsdlpull by  doxygen 1.4.6