src/wsdlparser/WsdlParser.cpp

00001 /* 
00002  * wsdlpull - A C++ parser for WSDL (Web services description
00003  * language) 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 #ifdef _WIN32
00023 #include <windows.h>
00024 #else
00025 #include <unistd.h>
00026 #endif
00027 
00028 #include "xmlpull/osdir.h"
00029 #include "wsdlparser/WsdlParser.h"
00030 #include "wsdlparser/Soap.h"
00031 
00032 using namespace std;
00033 namespace WsdlPull{
00034 
00035 bool WsdlParser::useLocalSchema_=true;
00036 
00037 WsdlParser::WsdlParser(istream & in, ostream & out,
00038                        const std::string & schemaPath)
00039   :errorOccured_(false), 
00040    ostr(out),
00041    istr(in),
00042    state_ (START),
00043    element_(START),
00044    Doc_(0),
00045    xParser_(0),
00046    MAX_EXT_XML(256),
00047    schemaPath_(schemaPath)
00048 {
00049   initialize(false);
00050 }
00051 
00052 WsdlParser::WsdlParser(const std::string & Uri, ostream & out,
00053                        const std::string & schemaPath)
00054   :errorOccured_(false), 
00055    ostr(out),
00056    istr(std::cin),
00057    state_ (START),
00058    element_(START),
00059    Doc_(0),
00060    xParser_(0),
00061    MAX_EXT_XML(256),
00062    schemaPath_(schemaPath)
00063 {
00064   uri_ = Uri.substr(0,Uri.rfind('/') + 1);
00065   if(XmlUtils::fetchUri(Uri,wsdlFileName))
00066     {
00067       xmlStream.open(wsdlFileName.c_str());
00068       initialize(true);
00069     }
00070   else{
00071     
00072     error(Uri+" could not be opened");   
00073   }
00074 }
00075 
00076 void
00077 WsdlParser::initialize(bool file)
00078 {
00079   if (schemaPath_.empty()) {
00080 
00081 #if defined SCHEMADIR
00082     schemaPath_= SCHEMADIR;
00083 #else 
00084     schemaPath_= "src/schemas";
00085 #endif
00086   }
00087  
00088   if(file)
00089     xParser_= new XmlPullParser(xmlStream);
00090   else
00091     xParser_= new XmlPullParser(istr);
00092 
00093   xParser_->setFeature(FEATURE_PROCESS_NAMESPACES, true);
00094   xParser_->require(xParser_->START_DOCUMENT, "", "");
00095   messages_.clear();
00096   bindings_.clear();
00097   porttypes_.clear();
00098   wsdlExtensions_.clear();
00099   schemaParser_.clear();
00100   
00101   //add the schema for wsdl1.0 to parse arrayType
00102   SchemaParser * sParser=0;
00103   if (WsdlPull::WsdlParser::useLocalSchema_ == false ) {
00104     
00105     sParser = new SchemaParser (wsdlUri,wsdlUri,ostr);
00106   }
00107   else {
00108     
00109     sParser = new SchemaParser (schemaPath_+"wsdl10.xsd",
00110                                                wsdlUri,ostr,schemaPath_);
00111 
00112   }
00113   sParser->parseSchemaTag();
00114   schemaParser_.push_back(sParser);
00115 
00116   soap_ = new Soap(schemaPath_);
00117   addExtensibilityHandler (soap_);
00118   //add the schema for soap encoding uri
00119   sParser = new SchemaParser(soap_->getEncodingSchema(),
00120                              Soap::soapEncUri,ostr,schemaPath_);
00121   sParser->parseSchemaTag();
00122   schemaParser_.push_back(sParser);
00123 }
00124 
00125 
00126 WsdlParser::~WsdlParser()
00127 {
00128   size_t i = 0;
00129   for (list < const Message * >::iterator mi =
00130          messages_.begin(); mi != messages_.end();
00131        mi++)
00132     delete(*mi);
00133   for (list < Binding * >::iterator bi =
00134          bindings_.begin(); bi != bindings_.end();
00135        bi++)
00136     delete(*bi);
00137 
00138   for (list < Service*>::iterator si =services_.begin();
00139        si != services_.end();
00140        si++)
00141     delete(*si);
00142   
00143   for (list < PortType * >::iterator pti =
00144          porttypes_.begin(); pti != porttypes_.end();
00145        pti++)
00146     delete(*pti);
00147 
00148   for (i = 0; i < schemaParser_.size(); i++)
00149     delete schemaParser_[i];
00150             
00151   //  for (i = 0; i < Ops_.size(); i++)
00152   //  delete Ops_[i];
00153 
00154   for (list < string * >::iterator sti =
00155          docs_list_.begin(); sti != docs_list_.end();
00156        sti++)
00157     delete(*sti);
00158 
00159   for (vector<ExtensionInfo>::iterator ie = wsdlExtensions_.begin();
00160        ie != wsdlExtensions_.end();
00161        ie++)
00162     delete ie->we;
00163   
00164   delete xParser_;
00165   xmlStream.close(); 
00166 
00167   // delete all the temp files
00168   oslink::directory dir(".");
00169   while (dir) {
00170     std::string fname = dir.next();
00171     if (fname.find(".wp-tmp") != std::string::npos)
00172       {
00173 #ifdef WIN32
00174         ::DeleteFile(fname.c_str());
00175 #else
00176         unlink(fname.c_str());
00177 #endif
00178       }
00179   }
00180 }
00181 
00182 const Binding *
00183 WsdlParser::getBinding()
00184 {
00185   if (element_ != BINDING)
00186     {
00187       error ("Attempted to extract a Binding when ,no binding was parsed",1);
00188       return 0;
00189     }
00190   else
00191     {
00192       return bindings_.back();
00193     }
00194 }
00195 
00196 void
00197 WsdlParser::addExtensibilityHandler(WsdlExtension * ext)
00198 {
00199   ExtensionInfo exi;
00200   exi.we=ext;
00201   exi.spe=0;
00202   wsdlExtensions_.push_back(exi);
00203 } 
00204 
00205 
00206 const Binding *
00207 WsdlParser::getBinding(const Qname & q)
00208 {
00209   Qname qn(q);
00210   if (!qn.getPrefix().empty())
00211     qn.setNamespace(getNamespace(qn.getPrefix()));
00212   else
00213     qn.setNamespace(tnsUri_);
00214   if (tnsUri_ != qn.getNamespace())
00215     return 0;
00216   for (list <Binding * >::iterator pBinding =
00217          bindings_.begin(); pBinding != bindings_.end();
00218        pBinding++)
00219     if ((*pBinding)->getName() == qn.getLocalName())
00220       return *pBinding;
00221   return 0;
00222 }
00223 
00224 
00225 const Service *
00226 WsdlParser::getService()
00227 {
00228   if (element_ != SERVICE){
00229     
00230     error ("Attempted to extract a Service when ,no service was parsed",1);
00231     return 0;
00232   }
00233   else{
00234 
00235     return services_.back();
00236   }
00237 }
00238 
00239 const Service *
00240 WsdlParser::getService(const Qname & q)
00241 {
00242   Qname qn(q);
00243   if (!qn.getPrefix().empty())
00244     qn.setNamespace(getNamespace(qn.getPrefix()));
00245   else
00246     qn.setNamespace(tnsUri_);
00247   if (tnsUri_ != qn.getNamespace())
00248     return 0;
00249   
00250   for (list <Service * >::iterator si =services_.begin();
00251        si != services_.end();
00252        si++)
00253     if ((*si)->getName() == qn.getLocalName())
00254       return *si;
00255   
00256   return 0;
00257 }
00258 
00259   void 
00260     WsdlParser::getServices(ServiceIterator &from, ServiceIterator &to)
00261   {
00262     if (services_.size() > 0)
00263     {
00264       from = services_.begin();
00265       to = services_.end();
00266     }
00267   }
00268 
00269 const PortType *
00270 WsdlParser::getPortType()
00271 {
00272   if (element_ != PORT_TYPE)
00273     {
00274       error ("Attempted to extract a PortType when ,no PortType was parsed",1);
00275       return 0;
00276     }
00277   else
00278     {
00279       return porttypes_.back();
00280     }
00281 }
00282 
00283 
00284 const PortType *
00285 WsdlParser::getPortType(const Qname & qn)
00286 {
00287   string name = qn.getLocalName();
00288   
00289   if (!qn.getPrefix().empty()){
00290     if(getNamespace(qn.getPrefix())!=tnsUri_)
00291       return 0;
00292   }
00293 
00294   for (PortType::cPortTypeIterator pPortType =porttypes_.begin();
00295        pPortType != porttypes_.end();
00296        pPortType++)
00297     if ((*pPortType)->getName() == name)
00298       return *pPortType;
00299   return 0;
00300 }
00301 
00302 
00303 bool
00304 WsdlParser::getOperations(const Qname & portType,
00305                           Operation::cOpIterator& begin,
00306                           Operation::cOpIterator& end)
00307 {
00308   const PortType *pt = getPortType(portType);
00309   if(pt){
00310     return pt->getOperations(begin,end);
00311   }
00312   else
00313     return false;
00314 }
00315  
00316 
00317 
00318 const Operation *
00319 WsdlParser::getOperation(const Qname & portType, const Qname & q)
00320 {
00321   const PortType *pt = getPortType(portType);
00322   int num = pt->getNumOps();
00323   if (num > 0)
00324     {
00325       const Operation *op = NULL;
00326       for (int i = 0; i < num; i++)
00327         {
00328           op = pt->getOperation(i);
00329           if (op->getName() == q.getLocalName())
00330             return op;
00331         }
00332     }
00333   return 0;
00334 }
00335 
00336 
00337 const Message *
00338 WsdlParser::getMessage()
00339 {
00340   if (element_ != MESSAGE)
00341     {
00342       error ("Attempted to extract a Message when ,no Message was parsed",1);
00343       return 0;
00344     }
00345   else
00346     {
00347       return messages_.back();
00348     }
00349 }
00350 
00351 
00352 const Message *
00353 WsdlParser::pgetMessage(const Qname & qn)
00354 {
00355   const Message*m=getMessage(qn);
00356   if(m==0){
00357     Message* newMessage = new Message(*this);
00358     newMessage->setName(qn.getLocalName());
00359     putMessage(newMessage);
00360     return newMessage;
00361   }else{
00362     return m;
00363   }
00364 }
00365 
00366 
00367 const Message *
00368 WsdlParser::getMessage(const Qname & qn)
00369 {
00370   string name = qn.getLocalName();
00371   if(!qn.getNamespace().empty() &&
00372      tnsUri_ != qn.getNamespace())
00373     return 0;
00374 
00375   for (list < const Message * >::iterator pMessage =
00376          messages_.begin(); pMessage != messages_.end();
00377        pMessage++)
00378     if ((*pMessage)->getName() == name)
00379       return *pMessage;
00380   
00381   return 0;
00382 }
00383 
00384 
00385 const SchemaParser *
00386 WsdlParser::getSchemaParser(string targetNamespace) const
00387 {
00388   if (targetNamespace == Schema::SchemaUri)
00389     return 0;
00390   for (size_t i = 0; i < schemaParser_.size(); i++){
00391     if (schemaParser_[i]->getNamespace() == targetNamespace)
00392       return (const SchemaParser *) schemaParser_[i];
00393   
00394     if (schemaParser_[i]->isImported(targetNamespace)) {
00395       
00396       return schemaParser_[i]->getImportedSchemaParser(targetNamespace);
00397     }
00398   }
00399   return 0;
00400 }
00401 
00402 
00403 
00404   ////////// private methods
00405 bool  isValidWsdlElement(int id)
00406 {
00407   if (id >= 0)
00408     return true;
00409 
00410   else
00411     return false;
00412 }
00413 
00414 
00415 int
00416 WsdlParser::peek(bool lookahead)
00417 {
00418 
00419   //event Type returned by XML pull parser
00420   int event_type, tmp_event_type = xParser_->getEventType();
00421   int tmpState = state_;
00422   if (state_ == END)
00423     return state_;
00424 
00425   do
00426     {
00427       if (lookahead == true || state_ == START || state_ == NONE)
00428         xParser_->nextTag();
00429 
00430       else
00431         return state_;
00432       event_type = xParser_->getEventType();
00433       string tag = xParser_->getName();
00434       switch (event_type)
00435         {
00436         case XmlPullParser::START_DOCUMENT:
00437           if (state_ != START)
00438             error("Syntax error at the start");
00439           break;
00440         case XmlPullParser::START_TAG:
00441           if (xParser_->getNamespace() != wsdlUri
00442               && xParser_->getNamespace() != Schema::SchemaUri)
00443             state_ = EXTENSIBILITY;
00444 
00445           else if (tag == "definitions")
00446             state_ = DEFINITION;
00447 
00448           else if (tag == "documentation")
00449             state_ = DOCUMENTATION;
00450 
00451           else if (tag == "annotation")
00452             state_ = ANNOTATION;
00453 
00454           else if (tag == "import")
00455             state_ = IMPORT;
00456 
00457           else if (tag == "schema")
00458             state_ = SCHEMA;
00459 
00460           else if (tag == "types")
00461             state_ = TYPES;
00462 
00463           else if (tag == "message")
00464             state_ = MESSAGE;
00465 
00466           else if (tag == "port")
00467             state_ = PORT;
00468 
00469           else if (tag == "operation")
00470             state_ = OPERATION;
00471 
00472           else if (tag == "portType")
00473             state_ = PORT_TYPE;
00474 
00475           else if (tag == "input")
00476             state_ = INPUT;
00477 
00478           else if (tag == "output")
00479             state_ = OUTPUT;
00480 
00481           else if (tag == "fault")
00482             state_ = FAULT;
00483 
00484           else if (tag == "part")
00485             state_ = PART;
00486 
00487           else if (tag == "binding")
00488             state_ = BINDING;
00489 
00490           else if (tag == "service")
00491             state_ = SERVICE;
00492 
00493           else
00494             error("Unknown Tag " + tag);
00495           break;
00496         case XmlPullParser::END_TAG:
00497           if (tag == "definitions")
00498             state_ = END;
00499 
00500           else
00501             {
00502               /*
00503                 If its one of the top level Wsdl elements
00504                 set the State to NONE
00505               */
00506               if (tag == "types" ||
00507                   tag == "message"||
00508                   tag == "documentation"||
00509                   tag == "annotation"||
00510                   tag == "portType" ||
00511                   tag == "import" ||
00512                   (tag == "binding"  &&
00513                    state_ != EXTENSIBILITY) ||
00514                   tag == "service")
00515                 return state_ = NONE;
00516               else
00517                 return peek(lookahead);   //get the next tag
00518             }
00519           break;
00520         case XmlPullParser::TEXT:
00521         case XmlPullParser::ENTITY_REF:
00522         case XmlPullParser::COMMENT:
00523         case XmlPullParser::PROCESSING_INSTRUCTION:
00524         case XmlPullParser::CDSECT:
00525           xParser_->getText();
00526           break;
00527         case XmlPullParser::DOCDECL:
00528           error("Doc Declaration ??");
00529           break;
00530         default:
00531           error("Unknown Wsdl tag");
00532           break;
00533         }
00534     } while (event_type != xParser_->END_DOCUMENT
00535              && tmpState == state_  &&event_type ==
00536              tmp_event_type);
00537   return state_;
00538 }
00539 
00540 
00541   //this method looks at the top level Wsdl elements
00542 int
00543 WsdlParser::next()
00544 {
00545   try
00546     {
00547       switch (peek(false))
00548         {
00549         case START:
00550           element_ = START;
00551           break;
00552         case DEFINITION:
00553           parseDefinitions();
00554           peek();
00555           element_ = DEFINITION;
00556           break;
00557         case DOCUMENTATION:
00558           Doc_=parseDoc();
00559           element_ = DOCUMENTATION;
00560           break;
00561         case ANNOTATION:
00562           parseAnnotation();
00563           element_ = ANNOTATION;
00564           break;
00565         case IMPORT:
00566           parseImport();
00567           element_ = IMPORT;
00568           break;
00569         case TYPES:
00570           parseTypes();
00571           element_ = TYPES;
00572           break;
00573         case MESSAGE:
00574           parseMessage();
00575           element_ = MESSAGE;
00576           break;
00577         case PORT_TYPE:
00578           parsePortType();
00579           element_ = PORT_TYPE;
00580           break;
00581         case EXTENSIBILITY:
00582           handleExtensibilityElement(DEFINITION);
00583           peek();
00584           element_ = EXTENSIBILITY;
00585           break;
00586         case SERVICE:
00587           parseService();
00588           element_ = SERVICE;
00589           break;
00590         case BINDING:
00591           parseBinding();
00592           element_ = BINDING;
00593           break;
00594         case END:
00595           element_ = END;
00596           return state_;
00597         default:
00598           error("Syntax error");
00599         }
00600       return state_;
00601     }
00602   catch(WsdlException we)
00603     {
00604       we.line = xParser_->getLineNumber();
00605       we.col = xParser_->getColumnNumber();
00606       errorOccured_ = true;
00607       element_ = END;
00608       //      ostr.seekp(0);we loose the other errors
00609       //      ostr.clear();
00610       ostr << we.description << " at " << we.line << "," << we.col << std::endl;
00611       return state_ = END;
00612     }
00613   catch(XmlPullParserException xe)
00614     {
00615       //      ostr.seekp(0);
00616       //      ostr.clear();
00617       errorOccured_ = true;
00618       element_ = END;
00619       return state_ = END;
00620     }
00621 }
00622 
00623 
00624   /*
00625     Parse a documentation tag
00626   */
00627 string* 
00628 WsdlParser::parseDoc()
00629 {
00630   string*  documentation = new string();
00631   if (state_ != DOCUMENTATION)
00632     error("syntax error");
00633 
00634   do
00635     {
00636       xParser_->nextToken();
00637       if (xParser_->getEventType() == xParser_->TEXT)
00638         *documentation += xParser_->getText();
00639       if (xParser_->getEventType() == xParser_->END_TAG
00640           && xParser_->getName()  == "documentation")
00641         break;
00642     } while (true);
00643   docs_list_.push_back(documentation);
00644   peek();
00645   return documentation;
00646 }
00647 
00648 
00649   /*
00650     Parse Annotation
00651   */
00652 void
00653 WsdlParser::parseAnnotation()
00654 {
00655   if (state_ != ANNOTATION)
00656     error("syntax error");
00657 
00658   do
00659     {
00660       xParser_->nextToken();
00661       if (xParser_->getEventType() == xParser_->END_TAG
00662           &&xParser_->getName() == "annotation")
00663         break;
00664     } while (true);
00665   peek();
00666 }
00667 
00668 
00669   /*Parses the definition tag
00670     If any extensibility namespaces are defined then the relevant
00671     information is stored
00672   */
00673 void
00674 WsdlParser::parseDefinitions()
00675 {
00676   if (state_ != DEFINITION)
00677     error("syntax error");
00678 
00679   tnsUri_ = xParser_->getAttributeValue("", "targetNamespace");
00680   int i = 0;
00681 
00682   for (i = xParser_->getNamespaceCount(xParser_->getDepth()) - 1;
00683        i > xParser_->getNamespaceCount(xParser_->getDepth() - 1) - 1; i--)
00684     {
00685       if (xParser_->getNamespaceUri(i) == tnsUri_)
00686         tnsPrefix_ = xParser_->getNamespacePrefix(i);
00687 
00688       /* 
00689        * Associate the extension prefixes with the handlers.
00690        * It is asssumed that by this time all the extensibility handlers have been registered .
00691        * Check if the namespace defined here matches that Uri ,whose namespace the handler handles .
00692        */
00693       for (size_t j = 0; j < wsdlExtensions_.size(); j++)
00694         if (wsdlExtensions_[j].we != 0 &&
00695             wsdlExtensions_[j].we->isNamespaceHandler(xParser_->getNamespaceUri(i)))
00696           {
00697             wsdlExtensions_[j].we->setNamespacePrefix(xParser_->
00698                                                       getNamespacePrefix
00699                                                       (i));
00700             //each extensibility handler allocates element ids in assigned range
00701             wsdlExtensions_[j].we->setStartId(MAX_EXT_XML * j + 1);
00702 
00703             /*
00704              * If there is a schema associated with the extensibility namespace
00705              * use the schema parser to parse its types.
00706              */
00707 
00708             SchemaParser * xtmpSchemaParser =
00709               new SchemaParser(wsdlExtensions_[j].we->getExtensibilitySchema(),
00710                                wsdlExtensions_ [j].we->getNamespace(),ostr,schemaPath_);
00711 
00712             //import the wsdl definition file as many binding schemas reference it
00713             xtmpSchemaParser->addImport(schemaParser_[0]);
00714             if (xtmpSchemaParser->parseSchemaTag())
00715               {
00716                 wsdlExtensions_[j].spe = xtmpSchemaParser;
00717                 wsdlExtensions_[j].we->
00718                   setSchemaParser(xtmpSchemaParser);
00719                 wsdlExtensions_[j].we->setWsdlParser(this);
00720               }
00721             else
00722               error("Error parsing extensibility schema for " +
00723                     wsdlExtensions_[j].we->getNamespace());
00724           }
00725     }
00726   int num_attr = xParser_->getAttributeCount();
00727   if (num_attr < 0)
00728     error("Atleast a targetNamespace attribute is needed");
00729   for (i = 0; i < num_attr; i++)
00730     {
00731       if (xParser_->getAttributeName(i) == "name")
00732         {
00733           name_ = xParser_->getAttributeValue(i);
00734           continue;
00735         }
00736 
00737       else if (xParser_->getAttributeName(i) != "targetNamespace")
00738         {                                         //this is to handle extensibility attributes
00739           handleExtensibilityAttributes(xParser_->getAttributePrefix(i),
00740                                         xParser_->getAttributeName(i));
00741         }
00742     }
00743   return;
00744 }
00745 
00746 
00747 void
00748 WsdlParser::parseImport()
00749 {
00750   if (state_ != IMPORT)
00751     error("syntax error");
00752   Imports imp (xParser_->getAttributeValue("", "namespace"),
00753                xParser_->getAttributeValue("", "location"));
00754   if (imp.ns == getNamespace() ) {
00755     
00756     std::string fname;
00757     ifstream wsdlStream;
00758     if(!imp.loc.empty())
00759       {
00760         if(XmlUtils::fetchUri(imp.loc,fname))
00761           {
00762             /*
00763              * If the schema definition was retrieved successfully 
00764              * process it and add all type definitions and
00765              * declaration to the current namespace
00766              */
00767             wsdlStream.open(fname.c_str());
00768             
00769             XmlPullParser * xpp = new XmlPullParser(wsdlStream);
00770             XmlPullParser * tmpXparser=xParser_;
00771             xParser_=xpp;
00772 
00773             xParser_->setFeature(FEATURE_PROCESS_NAMESPACES, true);
00774             xParser_->require(XmlPullParser::START_DOCUMENT, "", "");
00775             while (getNextElement () != WsdlParser::END);
00776             xParser_=tmpXparser;
00777             delete xpp;
00778           }else{
00779             error("Error while opening the included wsdl " + imp.loc);
00780           }
00781       }else{
00782         error("location is a required attribute for <import>");
00783       }
00784     imports_.push_back(imp);
00785     
00786     xParser_->nextTag();
00787   }
00788   peek();
00789 }
00790 
00791 
00792 void
00793 WsdlParser::parseMessage()
00794 {
00795   if (state_ != MESSAGE)
00796     error("syntax error");
00797   
00798   Message * m =0;
00799   int num_att = xParser_->getAttributeCount();
00800   std::string  n=xParser_->getAttributeValue("", "name");
00801   m=const_cast<Message*>(getMessage(n));
00802   if(!m){
00803     m= new Message(*this);
00804     m->setName(n);
00805     putMessage(m);
00806   }
00807         
00808   for (int i = 0; i < num_att; i++){
00809 
00810     if (!(xParser_->getAttributePrefix(i)).empty())
00811       m->addExtAttribute(handleExtensibilityAttributes
00812                          (xParser_->getAttributePrefix(i),
00813                           xParser_->getAttributeName(i)));
00814     
00815   }
00816   if (m->getName() == "")
00817     error("syntax error <message> name required");
00818   peek();
00819   try
00820     {
00821       if (state_ == DOCUMENTATION)
00822         {
00823           m->setDocumentation(parseDoc());
00824           //          peek();
00825         }
00826 
00827       //parse all the parts in the message
00828       //TODO .if a part has a type reference ,check that only one part is allowed in the message
00829       if (state_ == PART)
00830         {
00831           while (state_ == PART)
00832             {
00833               string p_name;
00834               int type_id = 0, schemaId = -1;
00835               Element* e=0;
00836               Part::PartRefType reftype = Part::None;
00837               int num_att = xParser_->getAttributeCount();
00838               int p_extId = 0;
00839               for (int i = 0; i < num_att; i++)
00840                 {
00841                   if ("name" == xParser_->getAttributeName(i) &&
00842                       //Wsdl attribute name must have a null prefix
00843                       (xParser_->getAttributePrefix(i)).empty())
00844                     p_name = xParser_->getAttributeValue(i);
00845 
00846                   else if (("type" == xParser_->getAttributeName(i)
00847                             &&xParser_->getAttributePrefix(i).empty())
00848                            ||("element" == xParser_->getAttributeName(i)
00849                               &&xParser_->getAttributePrefix(i).empty()))
00850                     {
00851                       if (reftype != Part::None)
00852                         error
00853                           ("either type or element must occur(only once) in part ");
00854                       if ("type" == xParser_->getAttributeName(i))
00855                         reftype = Part::Type;
00856 
00857                       else
00858                         reftype = Part::Elem;
00859                       Qname type(xParser_->getAttributeValue(i));
00860                       type.setNamespace(getNamespace(type.getPrefix()));
00861                       if (reftype == Part::Type)
00862                         {
00863 
00864                           //get the type id
00865                           type_id = getTypeId(type);
00866                           if (type_id == 0)
00867                             error("Could not resolve type " +
00868                                   type.getNamespace() + ":" +
00869                                   type.getLocalName());
00870                         }
00871 
00872                       else
00873                         {
00874                           //get the element id
00875                           e   = getElement(type);
00876                           if (e== 0 )
00877                             error("Could not resolve element " +
00878                                   type.getNamespace() + ":" +
00879                                   type.getLocalName());
00880                         }
00881 
00882                       //if the ref type is "element",the id is that of a global element and not a type
00883                       //get the schema parser of the namespace to which "type" belongs
00884                       schemaId = getSchema(type,reftype == Part::Type);
00885                     }
00886 
00887                   else if (!(xParser_->getAttributePrefix(i)).empty())
00888                     p_extId = handleExtensibilityAttributes(xParser_->
00889                                                             getAttributePrefix
00890                                                             (i),
00891                                                             xParser_->
00892 
00893                                                             getAttributeName
00894                                                             (i));
00895 
00896                   else
00897                     error("Syntax error");
00898                 }
00899               peek();
00900               if (state_ == DOCUMENTATION)
00901                 {
00902                   parseDoc();
00903                   //                  peek();
00904                 }
00905               if(reftype==Part::Elem)
00906                 m->addPart(p_name, reftype, (void*)(e) , schemaId);
00907               else
00908                 m->addPart(p_name, reftype, (void*)(&type_id) , schemaId);
00909               m->addExtElement(p_extId);
00910             }
00911         }
00912     }
00913   catch(WsdlException we)
00914     {
00915       we.line = xParser_->getLineNumber();
00916       we.col = xParser_->getColumnNumber();
00917       throw we;
00918     }
00919 
00920   //now parse the extensibility elements
00921   if (state_ == EXTENSIBILITY)
00922     {
00923       while (state_ == EXTENSIBILITY)
00924         {
00925           m->addExtElement(handleExtensibilityElement(MESSAGE));
00926           peek();
00927         }
00928     }
00929 
00930 
00931   return;
00932 }
00933 
00934 
00935 
00936 PortType * 
00937 WsdlParser::parsePortType()
00938 {
00939   if (state_ != PORT_TYPE)
00940     return 0;
00941 
00942   PortType * pt = new PortType(*this);
00943   int num_att = xParser_->getAttributeCount();
00944   for (int i = 0; i < num_att; i++){
00945 
00946     if ("name" == xParser_->getAttributeName(i) &&
00947         //Wsdl attribute name must have a null prefix
00948         (xParser_->getAttributePrefix(i)).empty())
00949       pt->setName(xParser_->getAttributeValue(i));
00950 
00951     else if (!(xParser_->getAttributePrefix(i)).empty()) {
00952         
00953       pt->addExtAttribute(handleExtensibilityAttributes
00954                           (xParser_->getAttributePrefix(i),
00955                            xParser_->getAttributeName(i)));
00956     }
00957     else {
00958        
00959       error("Syntax error.Unrecognized attribute");
00960     }
00961   }
00962   if (pt->getName() == "")
00963     error("syntax error <PortType> name required");
00964   
00965   peek();
00966   if (state_ == DOCUMENTATION) {
00967     
00968     pt->setDocumentation(parseDoc());
00969     //      peek();
00970   }
00971   if (state_ == OPERATION) {
00972 
00973     //parse all the operations in the port type
00974     while (state_ == OPERATION){
00975 
00976       Operation * op = parseOperation(pt);
00977       pt->addOp(op);
00978     }
00979     if (state_ == EXTENSIBILITY) {
00980 
00981       //now parse the extensibility elements
00982       while (state_ == EXTENSIBILITY){
00983         
00984         pt->addExtElement(handleExtensibilityElement(PORT_TYPE));
00985         peek();
00986       }
00987     }
00988   }
00989   putPortType(pt);
00990   return pt;
00991 }
00992 
00993 
00994 //Returns an operation element
00995 Operation *
00996 WsdlParser::parseOperation(PortType * p)
00997 {
00998   Operation * op = new Operation(*this,p);
00999   if (state_ != OPERATION)
01000     error("syntax error");
01001 
01002   int num_att = xParser_->getAttributeCount();
01003   for (int i = 0; i < num_att; i++){
01004 
01005     if ("name" == xParser_->getAttributeName(i) &&
01006         (xParser_->getAttributePrefix(i)).empty())
01007       op->setName(xParser_->getAttributeValue(i));
01008 
01009     //Wsdl attribute name must have a null prefix
01010 
01011     else if (!(xParser_->getAttributePrefix(i)).empty()) {
01012        
01013       op->addExtAttribute(handleExtensibilityAttributes
01014                           (xParser_->getAttributePrefix(i),
01015                            xParser_->getAttributeName(i)));
01016     }
01017 
01018     else if ("parameterOrder" == xParser_->getAttributeName(i)) {
01019 
01020     }
01021 
01022     else
01023       error("Syntax error..unrecognized attribute");
01024   }
01025   if (op->getName() == "")
01026     error("syntax error <operation> name required");
01027   peek();
01028   if (state_ == DOCUMENTATION)
01029     {
01030       op->setDocumentation(parseDoc());
01031       //      peek();
01032     }
01033   if (state_ == INPUT)
01034     {
01035       op->setMessage(pgetMessage(Qname(xParser_->getAttributeValue("", "message"))),
01036                      Input,
01037                      xParser_->getAttributeValue("", "name"));
01038 
01039       processMessageExtensibility(op,WsdlPull::Input);
01040       peek();
01041       if (state_ == OUTPUT)
01042         {
01043           op->setMessage(pgetMessage(Qname(xParser_->getAttributeValue("", "message"))),
01044                          Output,
01045                          xParser_->getAttributeValue("", "name"));
01046 
01047           processMessageExtensibility(op,WsdlPull::Output);
01048           peek();
01049         }
01050       while (state_ == FAULT)
01051         {
01052           op->setMessage(pgetMessage(Qname(xParser_->getAttributeValue("", "message"))),
01053                          Fault,
01054                          xParser_->getAttributeValue("", "name"));
01055           
01056           processMessageExtensibility(op,WsdlPull::Fault);
01057           peek();
01058         }
01059     }
01060 
01061   else if (state_ == OUTPUT)
01062     {
01063       op->setMessage(pgetMessage(Qname(xParser_->getAttributeValue("", "message"))),
01064                      Output,
01065                      xParser_->getAttributeValue("", "name"));
01066       processMessageExtensibility(op,WsdlPull::Output);
01067       peek();
01068       if (state_ == INPUT)
01069         {
01070           op->setMessage(pgetMessage(Qname(xParser_->getAttributeValue("", "message"))),
01071                          Input,
01072                          xParser_->getAttributeValue("", "name"));
01073           processMessageExtensibility(op,WsdlPull::Input);
01074           peek();
01075         }
01076       while (state_ == FAULT)
01077         {
01078           op->setMessage(pgetMessage(Qname(xParser_->getAttributeValue("", "message"))),
01079                          Fault,
01080                          xParser_->getAttributeValue("", "name"));
01081           processMessageExtensibility(op,WsdlPull::Fault);
01082           peek();
01083         }
01084     }
01085   if (state_ == DOCUMENTATION)
01086     {
01087       op->setDocumentation(parseDoc());
01088       //      peek();
01089     }
01090   if (state_ == EXTENSIBILITY)
01091     while (state_ == EXTENSIBILITY)
01092       {
01093         op->addExtElement(handleExtensibilityElement(OPERATION));
01094         peek();
01095       }
01096 
01097   //  Ops_.push_back(op);
01098   return op;
01099 }
01100 
01101 
01102 void
01103 WsdlParser::processMessageExtensibility(Operation * op,
01104                                         WsdlPull::MessageType mtype)
01105 {
01106 
01107   int num_att = xParser_->getAttributeCount();
01108   std::string message_name;
01109   for (int i = 0; i < num_att; i++){
01110 
01111     if ("name" == xParser_->getAttributeName(i) &&
01112         (xParser_->getAttributePrefix(i)).empty())
01113       message_name = xParser_->getAttributeValue(i);
01114 
01115     //Wsdl attribute name must have a null prefix
01116 
01117     else if (!(xParser_->getAttributePrefix(i)).empty()) {
01118        
01119       op->addMessageExtensibility(mtype,handleExtensibilityAttributes
01120                                   (xParser_->getAttributePrefix(i),
01121                                    xParser_->getAttributeName(i)));
01122     }
01123   }
01124 }
01125 
01126 void
01127 WsdlParser::parseTypes()
01128 {
01129   peek();
01130   if (state_ == DOCUMENTATION)
01131     {
01132       parseDoc();
01133       //      peek();
01134     }
01135   try
01136     {
01137       while (state_ == SCHEMA)
01138         {
01139           SchemaParser *sParser=new SchemaParser(xParser_, tnsUri_,ostr,schemaPath_);
01140               sParser->setUri(uri_);
01141           sParser->addImport(schemaParser_[0]);//soap encoding schema
01142           sParser->addImport(schemaParser_[1]);//wsdl schema for wsdl:arrayType
01143               
01144                         
01145           if (!sParser->parseSchemaTag())
01146             error("Error parsing schema types for "+tnsUri_);
01147           else
01148             schemaParser_.push_back(sParser);
01149           peek();
01150           error(sParser->getNamespace() +" schema parsed",2);
01151         }
01152       for (size_t i = 2; i < schemaParser_.size(); i++)
01153         {
01154           
01155           for (size_t j = 2; j < schemaParser_.size(); j++) {
01156                           
01157                            if (schemaParser_[i]->isImported(schemaParser_[j]->getNamespace()))
01158                                    schemaParser_[i]->addImport(schemaParser_[j]);
01159                   }
01160            
01161                 
01162           if (!schemaParser_[i]->finalize())
01163             error("Invalid schema");
01164         }
01165       
01166     } 
01167   catch(SchemaParserException spe)
01168     {
01169       WsdlException we(spe.description);
01170       we.col = spe.col;
01171       we.line = spe.line;
01172       we.WsdlState = state_;
01173       throw we;
01174     }
01175 }
01176 
01177 
01178 void
01179 WsdlParser::putMessage(Message * m)
01180 {
01181 
01182   //m->setId (nMessage++);
01183   messages_.push_back(m);
01184 } 
01185 
01186 
01187 void
01188 WsdlParser::putBinding(Binding * bn)
01189 {
01190   bindings_.push_back(bn);
01191 } 
01192 
01193 void
01194 WsdlParser::putPortType(PortType * pt)
01195 {
01196   porttypes_.push_back(pt);
01197 } 
01198 
01199 
01200 int
01201 WsdlParser::handleExtensibilityElement(int parent)
01202 {
01203   WsdlExtension * we = getExtensibilityHandler(xParser_->getNamespace());
01204   if (we == 0) {
01205     xParser_->skipSubTree();
01206     return 0;
01207   }
01208 
01209   else
01210     return we->handleElement(parent, xParser_);
01211 }
01212 
01213 
01214 int
01215 WsdlParser::handleExtensibilityAttributes(string prefix, string name)
01216 {
01217   WsdlExtension * we = getExtensibilityHandler(getNamespace(prefix));
01218   if (we == 0)
01219     return 0;
01220 
01221   else
01222     return we->handleAttribute(state_, name, xParser_);
01223 }
01224 
01225 WsdlExtension *
01226 WsdlParser::getExtensibilityHandler(const std::string &Ns)
01227 {
01228   for (size_t i = 0; i < wsdlExtensions_.size(); i++)
01229     if (wsdlExtensions_[i].we != 0 &&
01230         (wsdlExtensions_[i].we->isNamespaceHandler(Ns)))
01231       return wsdlExtensions_[i].we;
01232   return 0;
01233 }
01234 
01235 WsdlExtension *
01236 WsdlParser::getExtensibilityHandler(int extId)
01237 {
01238   for (size_t i = 0; i < wsdlExtensions_.size(); i++)
01239     if (wsdlExtensions_[i].we != 0 &&
01240         (extId >= wsdlExtensions_[i].we->getStartId()&&
01241          extId < MAX_EXT_XML + wsdlExtensions_[i].we->getStartId()))
01242       return wsdlExtensions_[i].we;
01243   return 0;
01244 }
01245 
01246 
01247 void
01248 WsdlParser::parseBinding()
01249 {
01250 
01251   Binding * bn = new Binding(*this);
01252   const PortType *pt = 0;
01253   int opBinding, inputBinding, outputBinding, faultBinding, index,
01254     bindingInfo;
01255   opBinding = inputBinding = outputBinding = faultBinding = index =
01256     bindingInfo = 0;
01257   if (state_ != BINDING)
01258     error("syntax error");
01259   int num_att = xParser_->getAttributeCount();
01260   int i;
01261   WsdlExtension* bindingExtension;
01262 
01263   for (i = 0; i < num_att; i++)
01264     {
01265       if ("name" == xParser_->getAttributeName(i) &&
01266           (xParser_->getAttributePrefix(i)).empty())
01267         bn->setName(xParser_->getAttributeValue(i));
01268 
01269       else if ("type" == xParser_->getAttributeName(i) &&
01270                (xParser_->getAttributePrefix(i)).empty())
01271         {
01272           Qname q(xParser_->getAttributeValue(i));
01273           pt = getPortType(q);
01274           if (!pt) 
01275             error("Unknown port type "+ q.getLocalName());
01276           bn->setPortType(pt);
01277           (const_cast<PortType*>(pt))->setBinding(bn);
01278         }
01279 
01280       else
01281         error("Syntax error..unrecognized attribute");
01282     }
01283   peek();
01284 
01285   if (state_ == DOCUMENTATION) {
01286 
01287     bn->setDocumentation(parseDoc());
01288     //      peek();
01289   }
01290   if (state_ == EXTENSIBILITY) {
01291 
01292     while (state_ == EXTENSIBILITY) {
01293 
01294       bn->setBindingInfo(bindingInfo =
01295                          handleExtensibilityElement(BINDING));
01296       bindingExtension=getExtensibilityHandler(bindingInfo);
01297       
01298       if(bindingExtension)
01299         bn->setBindingMethod(bindingExtension->getNamespace());
01300       peek();
01301     }
01302   }
01303   while (state_ == OPERATION){
01304     
01305     num_att = xParser_->getAttributeCount();
01306     const Operation *op = NULL;
01307     for (i = 0; i < num_att; i++){
01308 
01309       if ("name" == xParser_->getAttributeName(i) &&
01310           (xParser_->getAttributePrefix(i)).empty()){
01311 
01312         Qname q(xParser_->getAttributeValue(i));
01313         op = pt->getOperation(q);
01314       }
01315 
01316       else
01317         error("Unrecognized attribute");
01318     }
01319     index = bn->addOperation(op);
01320     peek();
01321 
01322     while (state_ == EXTENSIBILITY) {
01323 
01324       opBinding = handleExtensibilityElement(OPERATION);
01325       if(opBinding) bn->addOpBinding(index, opBinding);
01326       peek();
01327     }
01328 
01329     if (state_ == DOCUMENTATION) {
01330 
01331       parseDoc();
01332     }
01333     if (state_ == INPUT) {
01334 
01335       peek();
01336       while (state_ == EXTENSIBILITY){
01337         
01338         inputBinding = handleExtensibilityElement(OPERATION);
01339         if(inputBinding) bn->addInputBinding(index, inputBinding);
01340         peek();
01341       }
01342     }
01343     if (state_ == OUTPUT) {
01344 
01345       peek();
01346       while (state_ == EXTENSIBILITY){
01347 
01348         outputBinding = handleExtensibilityElement(OPERATION);
01349         if(outputBinding) bn->addOutputBinding(index, outputBinding);
01350         peek();
01351       }
01352     }
01353     while (state_ == FAULT) {
01354 
01355       peek();
01356       while (state_ == EXTENSIBILITY){
01357 
01358         faultBinding = handleExtensibilityElement(OPERATION);
01359         peek();
01360         if(faultBinding) bn->addFaultBinding(index, faultBinding);
01361       }
01362     }
01363   }
01364   putBinding(bn);
01365 }
01366 
01367 
01368 void
01369 WsdlParser::parseService()
01370 {
01371   if (state_ != SERVICE)
01372     error("Syntax error");
01373   string serviceName;
01374   Service * sv = new Service(*this);
01375   int num_att = xParser_->getAttributeCount();
01376   int i;
01377   for (i = 0; i < num_att; i++) {
01378 
01379     if ("name" == xParser_->getAttributeName(i) &&
01380         (xParser_->getAttributePrefix(i)).empty())
01381       serviceName = xParser_->getAttributeValue(i);
01382 
01383     else
01384       error("Unrecognized attribute");
01385   }
01386   sv->setName(serviceName);
01387   peek();
01388   if (state_ == DOCUMENTATION) {
01389 
01390     sv->setDocumentation(parseDoc());
01391   }
01392   while (state_ == PORT) {
01393 
01394     string bnName,portName;
01395     Binding * bn = 0;;
01396     int serviceExtId = 0;
01397     num_att = xParser_->getAttributeCount();
01398     for (i = 0; i < num_att; i++) {
01399 
01400       if ("binding" == xParser_->getAttributeName(i) &&
01401           (xParser_->getAttributePrefix(i)).empty()) {
01402         
01403         bnName = xParser_->getAttributeValue(i);
01404       }
01405       else if ("name" == xParser_->getAttributeName(i)) {
01406         
01407         portName = xParser_->getAttributeValue(i);
01408       }
01409     }
01410     //    Qname bindingName(bnName);
01411     bn = (Binding *) getBinding(bnName);
01412     peek();
01413     if (state_ == DOCUMENTATION) {
01414         
01415       parseDoc();
01416       //          peek();
01417     }
01418     if (state_ == EXTENSIBILITY) {
01419         
01420       serviceExtId = handleExtensibilityElement(BINDING);
01421       peek();
01422     }
01423     if (bn != 0)
01424       bn->addServiceExtId(serviceExtId);
01425 
01426     sv->addPort(portName,bn,serviceExtId);
01427   }
01428   services_.push_back(sv);
01429 }
01430 
01431 
01432 /*
01433  * returns the id of the schema to which "type" 
01434  * or "element" belongs
01435  */
01436 int
01437 WsdlParser::getSchema(const Qname & name,bool isType)
01438 {
01439   Qname type = name;
01440   type.setNamespace(getNamespace(type.getPrefix()));
01441 
01442   //this is a primitve type ,simple instance of schemaparser will do. 
01443  if (name.getNamespace() == Schema::SchemaUri)
01444     return 0;        
01445 
01446 
01447   for (size_t i = 0; i < schemaParser_.size(); i++) {
01448           
01449           //check in the schema parser which defines the namespace or imports it
01450           
01451         if( schemaParser_[i]->getNamespace() == type.getNamespace() ||
01452                 schemaParser_[i]->isImported(type.getNamespace())) {
01453                         
01454                 //check for definitions
01455                         
01456     if ((isType && schemaParser_[i]->getTypeId(name) != Schema::XSD_INVALID) ||
01457                 (!isType && schemaParser_[i]->getElement(name) != 0))
01458                  
01459           return i;
01460                 
01461     }
01462   }
01463   return -1;
01464 }
01465 
01466 Element *
01467 WsdlParser::getElement(const Qname& name)
01468 {
01469   int i = getSchema(name,false);
01470   if (i >= 0)
01471     return const_cast<Element*>(schemaParser_[i]->getElement(name));
01472   else
01473     return 0;
01474 }
01475 
01476 int
01477 WsdlParser::getTypeId(const Qname & type)
01478 {
01479   
01480   int i = getSchema(type,true);
01481   Qname t=type;
01482  
01483   if (i >= 0)
01484     return schemaParser_[i]->getTypeId(t);
01485 
01486   else
01487     return 0;
01488 }
01489 
01490 void
01491 WsdlParser::getSchemaParsers(std::vector<SchemaParser* >::iterator & from,
01492                              std::vector<SchemaParser* >::iterator & to)
01493 {
01494   
01495   from=schemaParser_.begin();
01496   from++;
01497   from++;
01498   to=schemaParser_.end();
01499   return ;
01500 }
01501 
01502 void
01503 WsdlParser::error(string s,int level)
01504 {
01505   if(level==0){
01506 
01507     WsdlException we("Wsdl Parser Exception : " + s);
01508     if(xParser_){
01509 
01510       we.line = xParser_->getLineNumber();
01511       we.col = xParser_->getColumnNumber();
01512     }
01513     we.WsdlState = state_;
01514     errorOccured_ = true;
01515     throw we;
01516   }
01517 #ifdef LOGGING
01518   else if (level == 1) {
01519 
01520     ostr<<"Wsdl parser warning : "<<s<<endl;
01521   }
01522   else if (level == 2) {
01523 
01524     ostr<<"Wsdl parser info : "<<s<<endl;
01525   }
01526 #endif
01527 }
01528 
01529 bool
01530 WsdlParser::getBindings(Binding::cBindingIterator & begin,
01531                         Binding::cBindingIterator & end)const
01532 {
01533   if(bindings_.size()>0){
01534     
01535     begin=bindings_.begin();
01536     end=bindings_.end();
01537     return true;
01538   }
01539   else
01540     return false;
01541 }
01542 
01543 bool
01544 WsdlParser::getPortTypes(PortType::cPortTypeIterator& begin,
01545                          PortType::cPortTypeIterator& end)const
01546 {
01547   if(porttypes_.size()>0){
01548     
01549     begin=porttypes_.begin();
01550     end=porttypes_.end();
01551     return true;
01552   }
01553   else
01554     return false;
01555 }
01556 
01557 int
01558 WsdlParser::getNumSchemas() const
01559 {
01560   return schemaParser_.size() - 2;
01561   //soap-enc and wsdl schema are parsed by default
01562 }
01563 
01564 void
01565 WsdlParser::setSchemaPath(const std::string & schemaPath)
01566 {
01567         schemaPath_ = schemaPath;
01568         soap_->setSchemaPath(schemaPath);
01569 }
01570 
01571 }

Generated on Sun Aug 10 00:07:40 2008 for wsdlpull by  doxygen 1.4.6