xml-rpc-api2cpp.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #include <iostream>
  2. #include <stdexcept>
  3. #include "xmlrpc-c/oldcppwrapper.hpp"
  4. #include "DataType.hpp"
  5. #include "XmlRpcFunction.hpp"
  6. #include "XmlRpcClass.hpp"
  7. #include "SystemProxy.hpp"
  8. using namespace std;
  9. #define NAME "xml-rpc-api2cpp"
  10. #define VERSION "0.1"
  11. /*----------------------------------------------------------------------------
  12. Command line
  13. -----------------------------------------------------------------------------*/
  14. class cmdlineInfo {
  15. public:
  16. string serverUrl;
  17. string methodPrefix;
  18. string localClass;
  19. cmdlineInfo(int const argc,
  20. const char ** const argv);
  21. private:
  22. cmdlineInfo();
  23. };
  24. cmdlineInfo::cmdlineInfo(int const argc,
  25. const char ** const argv) {
  26. if (argc-1 != 3) {
  27. cerr << argv[0] << ": Usage:" << endl
  28. << " xml-rpc-api2cpp <server_url> <method_prefix> <local_class>"
  29. << endl << endl
  30. << "Sample arguments:" << endl
  31. << " server_url = http://localhost/RPC2" << endl
  32. << " method_prefix = system" << endl
  33. << " local_class = SystemProxy" << endl;
  34. exit(1);
  35. }
  36. this->serverUrl = string(argv[1]);
  37. this->methodPrefix = string(argv[2]);
  38. this->localClass = string(argv[3]);
  39. }
  40. static XmlRpcClass
  41. getClassInfo(string const& serverUrl,
  42. string const& classPrefix,
  43. string const& className) {
  44. /*----------------------------------------------------------------------------
  45. Connect to a remote server and extract the information we'll need to
  46. build a proxy class.
  47. -----------------------------------------------------------------------------*/
  48. XmlRpcClass info(className);
  49. SystemProxy system(serverUrl);
  50. XmlRpcValue const methods(system.listMethods());
  51. size_t const end = methods.arraySize();
  52. for (size_t i = 0; i < end; ++i) {
  53. // Break the method name into two pieces.
  54. string const methodName(methods.arrayGetItem(i).getString());
  55. size_t const lastDot(methodName.rfind('.'));
  56. string methodPrefix;
  57. string functionName;
  58. if (lastDot == string::npos) {
  59. methodPrefix = "";
  60. functionName = methodName;
  61. } else {
  62. methodPrefix = string(methodName, 0, lastDot);
  63. functionName = string(methodName, lastDot + 1);
  64. }
  65. if (methodPrefix == classPrefix) {
  66. // It's a method User cares about
  67. string const help(system.methodHelp(methodName));
  68. XmlRpcValue const signatureList(
  69. system.methodSignature(methodName));
  70. if (signatureList.getType() != XMLRPC_TYPE_ARRAY) {
  71. // It must be the string "undef", meaning the server
  72. // won't tell us any signatures.
  73. cerr << "Skipping method " << methodName << " "
  74. << "because server does not report any signatures "
  75. << "for it (via system.methodSignature method)"
  76. << endl;
  77. } else {
  78. // Add this function to our class information.
  79. XmlRpcFunction const method(functionName,
  80. methodName,
  81. help,
  82. signatureList);
  83. info.addFunction(method);
  84. }
  85. }
  86. }
  87. return info;
  88. }
  89. static void
  90. printHeader(ostream & out,
  91. XmlRpcClass const& classInfo) {
  92. /*----------------------------------------------------------------------------
  93. Print a complete header for the specified class.
  94. -----------------------------------------------------------------------------*/
  95. string const className(classInfo.className());
  96. try {
  97. out << "// " << className << ".h - xmlrpc-c C++ proxy class" << endl;
  98. out << "// Auto-generated by xml-rpc-api2cpp." << endl;
  99. out << endl;
  100. string const headerSymbol("_" + className + "_H_");
  101. out << "#ifndef " << headerSymbol << endl;
  102. out << "#define " << headerSymbol << " 1" << endl;
  103. out << endl;
  104. out << "#include <xmlrpc-c/oldcppwrapper.hpp>" << endl;
  105. out << endl;
  106. classInfo.printDeclaration(cout);
  107. out << endl;
  108. out << "#endif /* " << headerSymbol << " */" << endl;
  109. } catch (exception const& e) {
  110. throw(logic_error("Failed to generate header for class " +
  111. className + ". " + e.what()));
  112. }
  113. }
  114. static void
  115. printCppFile(ostream & out,
  116. XmlRpcClass const& classInfo) {
  117. /*----------------------------------------------------------------------------
  118. Print a complete definition for the specified class.
  119. -----------------------------------------------------------------------------*/
  120. string const className(classInfo.className());
  121. try {
  122. out << "// " << className << ".cc - xmlrpc-c C++ proxy class" << endl;
  123. out << "// Auto-generated by xml-rpc-api2cpp." << endl;
  124. out << endl;
  125. out << "#include <xmlrpc-c/oldcppwrapper.hpp>" << endl;
  126. out << "#include \"" << className << ".h\"" << endl;
  127. classInfo.printDefinition(cout);
  128. } catch (XmlRpcFault const& fault) {
  129. throw(logic_error("Failed to generate definition for class " +
  130. className + ". " + fault.getFaultString()));
  131. }
  132. }
  133. int
  134. main(int const argc,
  135. const char ** const argv) {
  136. string const progName(argv[0]);
  137. cmdlineInfo const cmdline(argc, argv);
  138. int retval;
  139. XmlRpcClient::Initialize(NAME, VERSION);
  140. try {
  141. XmlRpcClass system = getClassInfo(cmdline.serverUrl,
  142. cmdline.methodPrefix,
  143. cmdline.localClass);
  144. printHeader(cout, system);
  145. cout << endl;
  146. printCppFile(cout, system);
  147. retval = 0;
  148. } catch (XmlRpcFault& fault) {
  149. cerr << progName << ": XML-RPC fault #" << fault.getFaultCode()
  150. << ": " << fault.getFaultString() << endl;
  151. retval = 1;
  152. } catch (logic_error& err) {
  153. cerr << progName << ": " << err.what() << endl;
  154. retval = 1;
  155. } catch (...) {
  156. cerr << progName << ": Unknown exception" << endl;
  157. retval = 1;
  158. }
  159. XmlRpcClient::Terminate();
  160. return retval;
  161. }