Back to index

nordugrid-arc-nox  1.1.0~rc6
wsdl2hed.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <arc/XMLNode.h>
00006 #include <string>
00007 #include <iostream>
00008 #include <fstream>
00009 #include <glibmm/fileutils.h>
00010 #include <algorithm>
00011 #include <unistd.h>
00012 #include <string.h>
00013 
00014 #include "schemaconv.h"
00015 
00016 Arc::NS ns;
00017 
00018 struct to_upper {
00019   int operator() (int ch)
00020   {
00021     return std::toupper(ch);
00022   }
00023 };
00024 
00025 struct to_lower {
00026   int operator() (int ch)
00027   {
00028     return std::tolower(ch);
00029   }
00030 };
00031 
00032 static void std_h_header(std::string &name, std::ofstream &h)
00033 {
00034     std::string uname = name;
00035     std::transform(name.begin(), name.end(), uname.begin(), to_upper());
00036     h << "// Generated by wsdl2hed " << std::endl;
00037     h << "#ifndef __ARC_" << uname << "_H__" << std::endl;
00038     h << "#define __ARC_" << uname << "_H__" << std::endl;
00039     h << std::endl;
00040     h << "#include <arc/message/Service.h>" << std::endl;
00041     h << "#include <arc/delegation/DelegationInterface.h>" << std::endl;
00042     h << "#include <arc/infosys/InformationInterface.h>" << std::endl;
00043     h << std::endl;
00044     h << "namespace " << name << " {" << std::endl;
00045     h << std::endl;
00046     h << "class " << name << "Service: public Arc::Service" << std::endl;
00047     h << "{" << std::endl;
00048     h << std::endl;
00049 }
00050 
00051 static void h_public_part(std::string &name, std::ofstream &h)
00052 {
00053     h << "    public:" << std::endl;
00054     h << "        " << name << "Service(Arc::Config *cfg);" << std::endl;
00055     h << "        virtual ~" << name << "Service(void);" << std::endl;
00056     h << "        virtual Arc::MCC_Status process(Arc::Message &inmsg, Arc::Message &outmsg);" << std::endl;
00057 }
00058 
00059 static void h_private_part(std::string &/*name*/, std::ofstream &h, Arc::XMLNode &xml)
00060 {
00061     h << "    private:" << std::endl;
00062     h << "        Arc::NS ns;" << std::endl;
00063     h << "        Arc::Logger logger;" << std::endl;
00064     h << "        Arc::DelegationContainerSOAP delegation;" << std::endl;
00065     h << "        Arc::InformationContainer infodoc;" << std::endl;
00066     h << "        Arc::MCC_Status make_soap_fault(Arc::Message &outmsg);" << std::endl;
00067     h << "        // Operations from WSDL" << std::endl;
00068     Arc::XMLNode op;
00069     for (int i = 0; (op = xml["wsdl:portType"]["wsdl:operation"][i]) == true; i++) {
00070         std::string n = (std::string) op.Attribute("name");
00071         if (!n.empty()) {
00072             h << "        Arc::MCC_Status " << n << "(Arc::XMLNode &in, Arc::XMLNode &out);" << std::endl;
00073         }
00074     }
00075 }
00076 
00077 static void std_cpp_header(std::string &name, std::ofstream &cpp)
00078 {   
00079     std::string lname = name;
00080     std::transform(name.begin(), name.end(), lname.begin(), to_lower());
00081     cpp << "// Generated by wsdl2hed" << std::endl;
00082     cpp << "#ifdef HAVE_CONFIG_H" << std::endl;
00083     cpp << "#include <config.h>" << std::endl;
00084     cpp << "#endif" << std::endl;
00085     cpp << std::endl;
00086     cpp << "#include <arc/loader/Loader.h>" << std::endl;
00087     cpp << "#include <arc/loader/ServiceLoader.h>" << std::endl;
00088     cpp << "#include <arc/message/PayloadSOAP.h>" << std::endl;
00089     cpp << "#include <arc/ws-addressing/WSA.h>" << std::endl;
00090     cpp << std::endl;
00091     cpp << "#include \"" << lname << ".h\"" << std::endl;
00092     cpp << std::endl;
00093     cpp << "namespace " << name << " {" << std::endl;
00094     cpp << std::endl;
00095     cpp << "static Arc::Service *get_service(Arc::Config *cfg, Arc::ChainContext *) { " << std::endl;
00096     cpp << "    return new " << name << "Service(cfg);" << std::endl;
00097     cpp << "}" << std::endl; 
00098 }
00099 
00100 static void cpp_public_part(std::string &name, std::ofstream &cpp, Arc::XMLNode &xml)
00101 {   
00102     cpp << std::endl;
00103     cpp << name << "Service::" << name << "Service(Arc::Config *cfg):Service(cfg),logger(Arc::Logger::rootLogger, \"" << name << "\")" << std::endl;
00104     cpp << "{" << std::endl;
00105     cpp << "    // Define supported namespaces" << std::endl;
00106     Arc::NS n = xml.Namespaces();
00107     Arc::NS::iterator it;
00108     for (it = n.begin(); it != n.end(); it++) {
00109         // Ignore some default namespace
00110         if (it->first != "soap" &&
00111             it->first != "SOAP-ENV" &&
00112             it->first != "SOAP-ENC" &&
00113             it->first != "wsdl" &&
00114             it->first != "xsd") {
00115                 cpp << "    ns[\"" << it->first << "\"]=\"" << it->second << "\";" << std::endl;
00116         }
00117     }
00118     cpp << "}" << std::endl;
00119     cpp << std::endl;
00120     cpp << name << "Service::~" << name << "Service(void)" << std::endl;
00121     cpp << "{" << std::endl;
00122     cpp << "}" << std::endl;
00123     cpp << std::endl;
00124     cpp << "Arc::MCC_Status " << name << "Service::process(Arc::Message &inmsg, Arc::Message &outmsg)" << std::endl;
00125     cpp << "{\n\
00126     // Both input and output are supposed to be SOAP\n\
00127     // Extracting payload\n\
00128     Arc::PayloadSOAP* inpayload = NULL;\n\
00129     try {\n\
00130       inpayload = dynamic_cast<Arc::PayloadSOAP*>(inmsg.Payload());\n\
00131     } catch(std::exception& e) { };\n\
00132     if(!inpayload) {\n\
00133       logger.msg(Arc::ERROR, \"input is not SOAP\");\n\
00134       return make_soap_fault(outmsg);\n\
00135     };\n\
00136     // Analyzing request\n\
00137     Arc::XMLNode op = inpayload->Child(0);\n\
00138     if(!op) {\n\
00139       logger.msg(Arc::ERROR, \"input does not define operation\");\n\
00140       return make_soap_fault(outmsg);\n\
00141     }; \n\
00142     logger.msg(Arc::VERBOSE,\"process: operation: %s\", op.Name());\n\
00143     Arc::PayloadSOAP* outpayload = new Arc::PayloadSOAP(ns);\n\
00144     Arc::PayloadSOAP& res = *outpayload;\n\
00145     Arc::MCC_Status ret = Arc::STATUS_OK;" << std::endl;
00146     
00147     cpp << "    "; // just becuase good indent of following if section
00148     Arc::XMLNode op;
00149     for (int i = 0; (op = xml["wsdl:portType"]["wsdl:operation"][i]) == true; i++) {
00150         std::string n = (std::string) op.Attribute("name");
00151         std::string msg = (std::string) op["output"].Attribute("message");
00152         cpp << "if(MatchXMLName(op, \"" << n << "\")) {" << std::endl;
00153         cpp << "        Arc::XMLNode r = res.NewChild(\"" << msg << "\");" << std::endl;
00154         cpp << "        ret = " << n << "(op, r);" << std::endl;
00155         cpp << "    } else ";
00156     }
00157     cpp << "if(MatchXMLName(op, \"DelegateCredentialsInit\")) {\n\
00158         if(!delegation.DelegateCredentialsInit(*inpayload,*outpayload)) {\n\
00159           delete inpayload;\n\
00160           return make_soap_fault(outmsg);\n\
00161         }\n\
00162     // WS-Property\n\
00163     } else if(MatchXMLNamespace(op,\"http://docs.oasis-open.org/wsrf/rp-2\")) {\n\
00164         Arc::SOAPEnvelope* out_ = infodoc.Process(*inpayload);\n\
00165         if(out_) {\n\
00166           *outpayload=*out_;\n\
00167           delete out_;\n\
00168         } else {\n\
00169           delete inpayload; delete outpayload;\n\
00170           return make_soap_fault(outmsg);\n\
00171         };\n\
00172     } else {\n\
00173         logger.msg(Arc::ERROR,\"SOAP operation is not supported: %s\", op.Name());\n\
00174         return make_soap_fault(outmsg);\n\
00175     };\n\
00176     // Set output\n\
00177     outmsg.Payload(outpayload);\n\
00178     return Arc::MCC_Status(ret);\n\
00179 }" << std::endl;
00180 
00181     cpp << std::endl;
00182 }
00183 
00184 static void cpp_private_part(std::string &name, std::ostream &cpp, Arc::XMLNode &xml)
00185 {
00186     cpp << "Arc::MCC_Status "<< name << "Service::make_soap_fault(Arc::Message& outmsg)\n\
00187 {\n\
00188     Arc::PayloadSOAP* outpayload = new Arc::PayloadSOAP(ns,true);\n\
00189     Arc::SOAPFault* fault = outpayload?outpayload->Fault():NULL;\n\
00190     if(fault) {\n\
00191         fault->Code(Arc::SOAPFault::Sender);\n\
00192         fault->Reason(\"Failed processing request\");\n\
00193     };\n\
00194     outmsg.Payload(outpayload);\n\
00195     return Arc::MCC_Status(Arc::STATUS_OK);\n\
00196 }" << std::endl << std::endl;
00197     Arc::XMLNode op;
00198     for (int i = 0; (op = xml["wsdl:portType"]["wsdl:operation"][i]) == true; i++) {
00199         std::string n = (std::string) op.Attribute("name");
00200         if (!n.empty()) {
00201             cpp << "Arc::MCC_Status " << name << "Service::" << n << "(Arc::XMLNode &in, Arc::XMLNode &out)" << std::endl;
00202             cpp << "{" << std::endl;
00203             cpp << "    return Arc::MCC_Status();" << std::endl;
00204             cpp << "}" << std::endl;
00205             cpp << std::endl;
00206         }
00207     }
00208 }
00209 
00210 static void std_h_footer(std::string &name, std::ofstream &h)
00211 {
00212     std::string uname = name;
00213     std::transform(name.begin(), name.end(), uname.begin(), to_upper());
00214     h << std::endl;
00215     h << "}; // class " << name << std::endl;
00216     h << "}; // namespace " << name << std::endl;
00217     h << "#endif // __ARC_" << uname << "_H__" << std::endl;
00218 }
00219 
00220 
00221 static void std_cpp_footer(std::string &name, std::ofstream &cpp)
00222 {
00223     std::string lname = name;
00224     std::transform(name.begin(), name.end(), lname.begin(), to_lower());
00225     cpp << "}; // namespace " << name << std::endl;
00226     cpp << std::endl;
00227     cpp << "service_descriptors ARC_SERVICE_LOADER = {" << std::endl;
00228     cpp << "    { \"" << lname << "\", 0, &" << name << "::get_service }," << std::endl;
00229     cpp << "    { NULL, 0, NULL }" << std::endl;
00230     cpp << "};" << std::endl;
00231 }
00232 
00233 static void gen_makefile_am(std::string &name)
00234 {
00235     std::string lname = name;
00236     std::transform(name.begin(), name.end(), lname.begin(), to_lower());
00237     std::ofstream m("Makefile.am");
00238     m << "pkglib_LTLIBRARIES = lib" << lname << ".la" << std::endl;
00239     m << "lib" << lname << "_la_SOURCES = " << lname << ".cpp " << lname << ".h" << std::endl;
00240     m << "lib" << lname << "_la_CXXFLAGS = $(GLIBMM_CFLAGS) $(LIBXML2_CFLAGS) -I$(top_srcdir)/include" << std::endl;
00241     m << "lib" << lname << "_la_LIBADD   = $(top_srcdir)/src/hed/libs/loader/libarcloader.la $(top_srcdir)/src/hed/libs/message/libarcmessage.la $(top_srcdir)/src/hed/libs/security/libarcsecurity.la $(top_srcdir)/src/hed/libs/ws/libarcws.la $(top_srcdir)/src/hed/libs/common/libarccommon.la" << std::endl;
00242     m << "lib" << lname << "_la_LDFLAGS = -no-undefined -avoid-version -module" << std::endl;
00243     m.close();
00244 }
00245 
00246 int main(int argc, char **argv)
00247 {
00248     bool parse_schema = false;
00249     if ((argc > 1) && (strcmp(argv[1],"-s") == 0)) {
00250       parse_schema = true;
00251       --argc; ++argv;
00252     }
00253     if (argc < 3) {
00254         std::cerr << "Invalid arguments" << std::endl;        
00255         return -1;
00256     }
00257     ns["wsdl"] = "http://schemas.xmlsoap.org/wsdl/";
00258     std::string xml_str = Glib::file_get_contents(argv[1]);
00259     Arc::XMLNode xml(xml_str);
00260     if (xml == false) {
00261         std::cerr << "Failed parse XML! " << std::endl;
00262         return -1;
00263     }
00264     /* {
00265         std::string str;
00266         xml.GetXML(str);
00267         std::cout << str << std::endl;
00268     }; */
00269 
00270     // xml.Namespaces(ns);
00271     std::string name = argv[2];
00272     std::string lname = name;
00273     std::transform(name.begin(), name.end(), lname.begin(), to_lower());
00274     std::string header_path = lname; 
00275     header_path += ".h";
00276     std::string cpp_path = lname; 
00277     cpp_path += ".cpp";
00278     
00279     std::ofstream h(header_path.c_str());
00280     if (!h) {
00281         std::cerr << "Cannot create: " << header_path << std::endl;
00282         exit(1);
00283     }
00284     std::ofstream cpp(cpp_path.c_str());
00285     if (!cpp) {
00286         unlink (header_path.c_str());
00287         std::cerr << "Cannot create: " << cpp_path << std::endl;
00288     }
00289 
00290     if(parse_schema) {
00291       if(!schemaconv(xml,h,cpp,lname)) return 1;
00292       return 0;
00293     }
00294     
00295     std_h_header(name, h);
00296     h_public_part(name, h);
00297     h_private_part(name, h, xml);
00298     std_h_footer(name, h);
00299     std_cpp_header(name, cpp);
00300     cpp_public_part(name, cpp, xml);
00301     cpp_private_part(name, cpp, xml);
00302     std_cpp_footer(name, cpp);
00303     h.close();
00304     cpp.close();
00305     gen_makefile_am(name);
00306    
00307     return 0;
00308 }