xmlrpc_cpp_proxy.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #include <iostream>
  2. #include <stdexcept>
  3. #include <cstdlib>
  4. #include "xmlrpcType.hpp"
  5. #include "xmlrpcMethod.hpp"
  6. #include "proxyClass.hpp"
  7. #include "systemProxy.hpp"
  8. using namespace std;
  9. /*----------------------------------------------------------------------------
  10. Command line
  11. -----------------------------------------------------------------------------*/
  12. class cmdlineInfo {
  13. public:
  14. string serverUrl;
  15. string methodPrefix;
  16. string localClass;
  17. cmdlineInfo(int const argc,
  18. const char ** const argv);
  19. private:
  20. cmdlineInfo();
  21. };
  22. cmdlineInfo::cmdlineInfo(int const argc,
  23. const char ** const argv) {
  24. if (argc-1 != 3) {
  25. cerr << "There are 3 arguments: server URL, "
  26. << "prefix for the methods to include (null to include all), "
  27. << "and name to give the generated proxy class. "
  28. << "You specified " << argc-1 << " arguments."
  29. << endl
  30. << "Example: "
  31. << "xmlrpc_cpp_proxy http://localhost/RPC2 system systemProxy"
  32. << endl;
  33. exit(1);
  34. }
  35. this->serverUrl = string(argv[1]);
  36. this->methodPrefix = string(argv[2]);
  37. this->localClass = string(argv[3]);
  38. }
  39. static proxyClass
  40. getClassInfo(string const& serverUrl,
  41. string const& classPrefix,
  42. string const& className) {
  43. /*----------------------------------------------------------------------------
  44. Connect to a remote server and extract the information we'll need to
  45. build a proxy class.
  46. -----------------------------------------------------------------------------*/
  47. proxyClass theClass(className);
  48. systemProxy system;
  49. xmlrpc_c::value_array methods(system.listMethods(serverUrl));
  50. unsigned int arraySize = methods.size();
  51. for (size_t i = 0; i < arraySize; ++i) {
  52. // Break the method name into two pieces.
  53. xmlrpc_c::value_string val = (methods.vectorValueValue())[i];
  54. string const methodName(static_cast<string>(val));
  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(serverUrl, methodName));
  68. xmlrpc_c::value const signatureList(
  69. system.methodSignature(serverUrl, methodName));
  70. if (signatureList.type() != xmlrpc_c::value::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. xmlrpcMethod const method(
  80. functionName,
  81. methodName,
  82. help,
  83. xmlrpc_c::value_array(signatureList));
  84. theClass.addFunction(method);
  85. }
  86. }
  87. }
  88. return theClass;
  89. }
  90. static void
  91. printHeader(ostream & out,
  92. proxyClass const& classInfo) {
  93. /*----------------------------------------------------------------------------
  94. Print a complete header for the specified class.
  95. -----------------------------------------------------------------------------*/
  96. string const className(classInfo.className());
  97. try {
  98. out << "// Interface definition for " << className << " class, "
  99. << "an XML-RPC FOR C/C++ proxy class" << endl;
  100. out << "// Generated by 'xmlrpc_cpp_proxy'" << endl;
  101. out << endl;
  102. string const headerSymbol("_" + className + "_H_");
  103. out << "#ifndef " << headerSymbol << endl;
  104. out << "#define " << headerSymbol << " 1" << endl;
  105. out << endl;
  106. out << "#include <string>" << endl;
  107. out << "#include <xmlrpc-c/client_simple.hpp>" << endl;
  108. out << endl;
  109. classInfo.printDeclaration(cout);
  110. out << endl;
  111. out << "#endif /* " << headerSymbol << " */" << endl;
  112. } catch (exception const& e) {
  113. throw(logic_error("Failed to generate header for class " +
  114. className + ". " + e.what()));
  115. }
  116. }
  117. static void
  118. printCppFile(ostream & out,
  119. proxyClass const& classInfo) {
  120. /*----------------------------------------------------------------------------
  121. Print a complete definition for the specified class.
  122. -----------------------------------------------------------------------------*/
  123. string const className(classInfo.className());
  124. try {
  125. out << "// " << className << " - "
  126. << "an XML-RPC FOR C/C++ proxy class" << endl;
  127. out << "// Generated by 'xmlrpc_cpp_proxy'" << endl;
  128. out << endl;
  129. out << "#include \"" << className << ".h\"" << endl;
  130. classInfo.printDefinition(cout);
  131. } catch (xmlrpc_c::fault const& f) {
  132. throw(logic_error("Failed to generate definition for class " +
  133. className + ". " + f.getDescription()));
  134. }
  135. }
  136. int
  137. main(int const argc,
  138. const char ** const argv) {
  139. string const myName(argv[0]);
  140. cmdlineInfo const cmdline(argc, argv);
  141. int retval;
  142. try {
  143. proxyClass system(getClassInfo(cmdline.serverUrl,
  144. cmdline.methodPrefix,
  145. cmdline.localClass));
  146. printHeader(cout, system);
  147. cout << endl;
  148. printCppFile(cout, system);
  149. retval = 0;
  150. } catch (xmlrpc_c::fault& f) {
  151. cerr << myName << ": XML-RPC fault #" << f.getCode()
  152. << ": " << f.getDescription() << endl;
  153. retval = 1;
  154. } catch (exception const& e) {
  155. cerr << myName << ": " << e.what() << endl;
  156. retval = 1;
  157. } catch (...) {
  158. cerr << myName << ": Unknown exception" << endl;
  159. retval = 1;
  160. }
  161. return retval;
  162. }