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