src/wsdlparser/Soap.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  */
00021 
00022 #include <sstream>
00023 #include "wsdlparser/Soap.h"
00024 using namespace std;
00025 
00026 namespace WsdlPull {
00027 /*
00028   TODO
00029   1.When the use is "encoded" the part must reference the an
00030   abstract type using the "type" attribute .
00031   2.Only Soap encoding style is supported
00032 */
00033 
00034 #include <iomanip>
00035 
00036 const std::string Soap::httpTransport = "http://schemas.xmlsoap.org/soap/http";
00037 const std::string Soap::httpBinding = "http://schemas.xmlsoap.org/wsdl/http/";
00038 const std::string Soap::soapEncUri = "http://schemas.xmlsoap.org/soap/encoding/";
00039 const std::string Soap::soapEnvUri = "http://schemas.xmlsoap.org/soap/envelope/";
00040 const std::string Soap::soapBindingUri ="http://schemas.xmlsoap.org/wsdl/soap/";
00041 
00042 Soap::Soap(const std::string & schemaPath)
00043   :sNamespace(soapBindingUri),
00044    startId(0),
00045    mySchemaParser(0),
00046    mySchemaValidator(0),
00047    wParser_(0),
00048    idCounter(0),
00049    schemaPath_(schemaPath)
00050 {
00051   header_.clear();
00052   body_.clear();
00053   location_.clear();
00054   ops_.clear();
00055   idTable.clear();
00056 }
00057 
00058 
00059 Soap::~Soap()
00060 {
00061   if (mySchemaParser)
00062     delete mySchemaParser;
00063   if (mySchemaValidator)
00064     delete mySchemaValidator;
00065 }
00066 
00067 std::string 
00068 Soap::getExtensibilitySchema(void)const
00069 {
00070   string path=schemaPath_;
00071   path+="soap.xsd";
00072   return path;
00073 }
00074 
00075 std::string
00076 Soap::getEncodingSchema(void)const
00077 {
00078  
00079   string path=schemaPath_;
00080   path+="soap-encoding.xsd";
00081   return path;
00082 }
00083 
00084 int 
00085 Soap::handleElement(int parent, XmlPullParser * xParser)
00086 {
00087   if (mySchemaParser == 0) {
00088    error("Could not parse soap extensibility elements");
00089     return 0;
00090   }
00091   string elemName = xParser->getName();
00092   int elemId = 0;
00093   Qname q(elemName);
00094   const  Element* e= mySchemaParser->getElement(q);
00095   if (e == 0) {
00096 
00097     error("Unknown element");
00098     return 0;
00099   }
00100   TypeContainer * t = new TypeContainer(e->getType(), mySchemaParser);
00101   
00102   try{
00103 
00104     mySchemaValidator->validate(xParser,e->getType(), t);
00105   } 
00106   catch (SchemaParserException spe) {
00107     
00108     error(spe.description + "Encountered error while validating {"+sNamespace +"}:"+elemName);
00109   }
00110   if (elemName == "binding")
00111     elemId = processBinding(t);
00112 
00113   else if (elemName == "operation")
00114     elemId = processOp(parent, t);
00115 
00116   else if (elemName == "body")
00117     elemId = processBody(parent, t);
00118 
00119   else if (elemName == "header")
00120     elemId = processHeader(parent, t);
00121 
00122   else if (elemName == "fault")
00123     elemId = processFault(parent, t);
00124 
00125   else if (elemName == "address")
00126     elemId = processAddress(parent, t);
00127   delete t;
00128   return elemId;
00129 }
00130 
00131 
00132 int
00133 Soap::handleAttribute(int parent, string att,
00134                       XmlPullParser * xParser)
00135 {
00136   return 0;
00137 }
00138 
00139 
00140 int  Soap::processBinding(TypeContainer * t)
00141 {
00142   TypeContainer * temp = 0;
00143   if ((temp = t->getAttributeContainer("transport")) != 0)
00144     {
00145       string tp = *((string *) (temp->getValue()));
00146       if (tp == httpTransport)
00147         transport_ = HTTP;
00148 
00149       else
00150         transport_ = NONE;
00151     }
00152 
00153   else
00154     transport_ = HTTP;
00155 
00156   /*
00157    * Assume default transport as HTTP
00158    */
00159   if ((temp = t->getAttributeContainer("style")) != 0)
00160     {
00161       string style = *((string *) (temp->getValue()));
00162       if (style == "rpc")
00163         style_ = RPC;
00164 
00165       else
00166         style_ = DOC;
00167     }
00168 
00169   else
00170     style_ = DOC;
00171   Qname binding("binding");
00172   IDTableIndex idi;
00173   idi.typeId=(mySchemaParser->getElement(binding))->getType();
00174   idi.index=0;
00175   idTable.push_back(idi);
00176   idCounter++;
00177   return startId + idCounter - 1;
00178 }
00179 
00180 
00181 int  Soap::processOp(int parent, TypeContainer * t)
00182 {
00183   TypeContainer * temp = 0;
00184   SoapOperationBinding sopb;
00185   
00186   if ((temp = t->getAttributeContainer("soapAction")) != 0)
00187     {
00188       string * s = (string *) (temp->getValue());
00189       if(s)
00190         sopb.soapAction = *s;
00191     }
00192 
00193   if ((temp = t->getAttributeContainer("style")) != 0)
00194     {
00195       string style = *((string *) (temp->getValue()));
00196       if (style == "rpc")
00197         sopb.style = RPC;
00198 
00199       else
00200         sopb.style = DOC;
00201     }
00202   else                                          //Use the binding element's style attribute
00203     sopb.style = style_;
00204   sopb.wsdlOpId = parent;
00205 
00206   ops_.push_back(sopb);
00207 
00208   Qname oprn("operation");
00209   IDTableIndex idi;
00210   idi.typeId=(mySchemaParser->getElement(oprn))->getType();
00211   idi.index=ops_.size()-1;
00212   idTable.push_back(idi);
00213   idCounter++;
00214   return startId + idCounter - 1;
00215 }
00216 
00217 
00218 int
00219 Soap::processBody(int parent, TypeContainer * t)
00220 {
00221   TypeContainer * temp = 0;
00222   string use;
00223   SoapMessageBinding smb;
00224 
00225   if ((temp = t->getAttributeContainer("use")) != 0)
00226     {
00227       use = *((string *) (temp->getValue()));
00228       if (use == "literal")
00229         smb.use = LITERAL;
00230       else
00231         smb.use = ENCODED;
00232     }
00233   else
00234     smb.use = LITERAL;
00235 
00236   if ((temp = t->getAttributeContainer("namespace")) != 0)
00237     {
00238       string * s = (string *) (temp->getValue());
00239       smb.urn = *s;
00240     }
00241   else{
00242     
00243     smb.urn="";
00244   }
00245 
00246   if ((temp = t->getAttributeContainer("encodingStyle")) != 0)
00247   {
00248     string * s = (string *) (temp->getValue());
00249     smb.encodingStyle = *s;
00250   }
00251   else{
00252 
00253     smb.encodingStyle="";
00254   }
00255 
00256   body_.push_back(smb);
00257 
00258   Qname body("body");
00259   IDTableIndex idi;
00260   idi.typeId=(mySchemaParser->getElement(body))->getType();
00261   idi.index=body_.size()-1;
00262   idTable.push_back(idi);
00263   idCounter++;
00264   return startId + idCounter - 1;
00265 }
00266 
00267 
00268 int
00269 Soap::processFault(int parent, TypeContainer *)
00270 {
00271   //TODO
00272   return startId + idCounter - 1;
00273 }
00274 
00275 
00276 int  
00277 Soap::processAddress(int parent, TypeContainer * t)
00278 {
00279   TypeContainer * temp = 0;
00280   string location;
00281 
00282   if ((temp = t->getAttributeContainer("location")) != 0)
00283     {
00284       string * s = (string *) (temp->getValue());
00285       if(s)
00286         location_.push_back(*s);
00287     }
00288   Qname address("address");
00289 
00290   IDTableIndex idi;
00291   idi.typeId=(mySchemaParser->getElement(address))->getType();
00292   idi.index=location_.size()-1;
00293   idTable.push_back(idi);
00294   idCounter++;
00295   return startId + idCounter - 1;
00296 }
00297 
00298 
00299 int
00300 Soap::processHeader(int parent, TypeContainer * t)
00301 {
00302   TypeContainer * temp = 0;
00303   Qname msg;
00304   std::string ns, part;
00305   Qname header("header");
00306   int partType;
00307   SoapHeaderBinding shb;
00308   if ((temp = t->getAttributeContainer("message")) != 0) {
00309     
00310     msg = *((Qname *) (temp->getValue()));
00311   }
00312   if ((temp = t->getAttributeContainer("namespace")) != 0) {
00313 
00314     ns = *((string *) (temp->getValue()));
00315   }
00316   if (!ns.empty()) 
00317     msg.setNamespace(ns);
00318   const Message *m = wParser_->getMessage(msg);
00319   if (m == 0) {
00320     error("Unkown message " + msg.getLocalName());
00321     return 0;
00322   }
00323   if ((temp = t->getAttributeContainer("parts")) != 0) {
00324     
00325     part = *((string *) (temp->getValue()));  //this is actually NMTOKENS
00326   }
00327   else if ((temp = t->getAttributeContainer("part")) != 0) {
00328     //some wsdls use 'part' instead of 'parts'
00329     part = *((string *) (temp->getValue()));  
00330   }
00331   partType = m->getPartType(part);
00332 
00333   if (partType == 0)
00334     error("Unkown part type :"+ part);
00335 
00336   shb.partId_= m->getPartIndex(part);
00337   shb.message_ = m;
00338   header_.push_back(shb);
00339 
00340   IDTableIndex idi;
00341   idi.typeId=(mySchemaParser->getElement(header))->getType();
00342   idi.index=header_.size()-1;
00343   idTable.push_back(idi);
00344 
00345   idCounter++;
00346   return startId + idCounter - 1;
00347 }
00348 
00349 
00350 void
00351 Soap::getSoapOperationInfo(int elemId, string & action, Soap::Style &style)
00352 {
00353   if (elemId - startId >= idCounter)            //invalid elem Id
00354     return;
00355   int opId = idTable[elemId - startId].index;
00356   action = ops_[opId].soapAction;
00357   style = ops_[opId].style;
00358 } 
00359 
00360 void  
00361 Soap::getSoapBodyInfo(int elemId, string &ns, Soap::Encoding &use, std::string &encodingStyle)
00362 {
00363   if (elemId - startId >= idCounter)            //invalid elem Id
00364     return;
00365   int bodyId = idTable[elemId - startId].index;
00366   ns = body_[bodyId].urn;
00367   use = body_[bodyId].use;
00368   encodingStyle = body_[bodyId].encodingStyle;
00369 } 
00370 
00371 void
00372 Soap::getSoapHeaderInfo(int elemId, int &partId, const Message* & m)
00373 {
00374   if (elemId - startId >= idCounter)            //invalid elem Id
00375     return;
00376   int headerId = idTable[elemId - startId].index;
00377   partId = header_[headerId].partId_;
00378   m = header_[headerId].message_;
00379 } 
00380 
00381 bool
00382 Soap::getServiceLocation(int elemId, std::string &location)
00383 {
00384   if (elemId - startId >= idCounter)            //invalid elem Id
00385     return false;
00386   int locId = idTable[elemId - startId].index;
00387   location = location_[locId];
00388   if(!location.empty())
00389     return true;
00390   else
00391     return false;
00392 } 
00393 
00394 bool 
00395 Soap::isSoapBody(int elemId)
00396 {
00397   Qname  body("body");
00398   if (elemId - startId >= idCounter)            //invalid elem Id
00399     return false;
00400   if (idTable[elemId - startId].typeId ==
00401       (mySchemaParser->getElement(body))->getType())
00402     return true;
00403   else
00404     return false;
00405 }
00406 
00407 
00408 bool 
00409 Soap::isSoapHeader(int elemId)
00410 {
00411   Qname  header("header");
00412   if (elemId - startId >= idCounter)            //invalid elem Id
00413     return false;
00414   if (idTable[elemId - startId].typeId ==
00415       (mySchemaParser->getElement(header))->getType())
00416     return true;
00417 
00418   else
00419     return false;
00420 }
00421 
00422 
00423 void
00424 Soap::error(std::string s)
00425 {
00426   wParser_->logger()<< "Soap Processing" << XmlUtils::dbsp << s << endl;
00427 }
00428 
00429 void
00430 Soap::setSchemaPath(const std::string & schemaPath)
00431 {
00432   schemaPath_ = schemaPath;
00433 }
00434 
00435 }

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