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

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