|
|
#include <iostream> |
|
|
#include <stdexcept> |
|
|
|
|
|
#include "xmlrpc-c/oldcppwrapper.hpp" |
|
|
|
|
|
#include "DataType.hpp" |
|
|
#include "XmlRpcFunction.hpp" |
|
|
#include "XmlRpcClass.hpp" |
|
|
#include "SystemProxy.hpp" |
|
|
|
|
|
using namespace std; |
|
|
|
|
|
#define NAME "xml-rpc-api2cpp" |
|
|
#define VERSION "0.1" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class cmdlineInfo { |
|
|
public: |
|
|
string serverUrl; |
|
|
string methodPrefix; |
|
|
string localClass; |
|
|
|
|
|
cmdlineInfo(int const argc, |
|
|
const char ** const argv); |
|
|
|
|
|
private: |
|
|
cmdlineInfo(); |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
cmdlineInfo::cmdlineInfo(int const argc, |
|
|
const char ** const argv) { |
|
|
|
|
|
if (argc-1 != 3) { |
|
|
cerr << argv[0] << ": Usage:" << endl |
|
|
<< " xml-rpc-api2cpp <server_url> <method_prefix> <local_class>" |
|
|
<< endl << endl |
|
|
<< "Sample arguments:" << endl |
|
|
<< " server_url = http://localhost/RPC2" << endl |
|
|
<< " method_prefix = system" << endl |
|
|
<< " local_class = SystemProxy" << endl; |
|
|
exit(1); |
|
|
} |
|
|
this->serverUrl = string(argv[1]); |
|
|
this->methodPrefix = string(argv[2]); |
|
|
this->localClass = string(argv[3]); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static XmlRpcClass |
|
|
getClassInfo(string const& serverUrl, |
|
|
string const& classPrefix, |
|
|
string const& className) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XmlRpcClass info(className); |
|
|
|
|
|
SystemProxy system(serverUrl); |
|
|
|
|
|
XmlRpcValue const methods(system.listMethods()); |
|
|
|
|
|
size_t const end = methods.arraySize(); |
|
|
|
|
|
for (size_t i = 0; i < end; ++i) { |
|
|
|
|
|
|
|
|
string const methodName(methods.arrayGetItem(i).getString()); |
|
|
size_t const lastDot(methodName.rfind('.')); |
|
|
|
|
|
string methodPrefix; |
|
|
string functionName; |
|
|
|
|
|
if (lastDot == string::npos) { |
|
|
methodPrefix = ""; |
|
|
functionName = methodName; |
|
|
} else { |
|
|
methodPrefix = string(methodName, 0, lastDot); |
|
|
functionName = string(methodName, lastDot + 1); |
|
|
} |
|
|
|
|
|
if (methodPrefix == classPrefix) { |
|
|
|
|
|
|
|
|
string const help(system.methodHelp(methodName)); |
|
|
XmlRpcValue const signatureList( |
|
|
system.methodSignature(methodName)); |
|
|
|
|
|
if (signatureList.getType() != XMLRPC_TYPE_ARRAY) { |
|
|
|
|
|
|
|
|
cerr << "Skipping method " << methodName << " " |
|
|
<< "because server does not report any signatures " |
|
|
<< "for it (via system.methodSignature method)" |
|
|
<< endl; |
|
|
} else { |
|
|
|
|
|
XmlRpcFunction const method(functionName, |
|
|
methodName, |
|
|
help, |
|
|
signatureList); |
|
|
info.addFunction(method); |
|
|
} |
|
|
} |
|
|
} |
|
|
return info; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
printHeader(ostream & out, |
|
|
XmlRpcClass const& classInfo) { |
|
|
|
|
|
|
|
|
|
|
|
string const className(classInfo.className()); |
|
|
|
|
|
try { |
|
|
out << "// " << className << ".h - xmlrpc-c C++ proxy class" << endl; |
|
|
out << "// Auto-generated by xml-rpc-api2cpp." << endl; |
|
|
out << endl; |
|
|
|
|
|
string const headerSymbol("_" + className + "_H_"); |
|
|
|
|
|
out << "#ifndef " << headerSymbol << endl; |
|
|
out << "#define " << headerSymbol << " 1" << endl; |
|
|
out << endl; |
|
|
out << "#include <xmlrpc-c/oldcppwrapper.hpp>" << endl; |
|
|
out << endl; |
|
|
|
|
|
classInfo.printDeclaration(cout); |
|
|
|
|
|
out << endl; |
|
|
out << "#endif /* " << headerSymbol << " */" << endl; |
|
|
} catch (exception const& e) { |
|
|
throw(logic_error("Failed to generate header for class " + |
|
|
className + ". " + e.what())); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
printCppFile(ostream & out, |
|
|
XmlRpcClass const& classInfo) { |
|
|
|
|
|
|
|
|
|
|
|
string const className(classInfo.className()); |
|
|
|
|
|
try { |
|
|
out << "// " << className << ".cc - xmlrpc-c C++ proxy class" << endl; |
|
|
out << "// Auto-generated by xml-rpc-api2cpp." << endl; |
|
|
out << endl; |
|
|
|
|
|
out << "#include <xmlrpc-c/oldcppwrapper.hpp>" << endl; |
|
|
out << "#include \"" << className << ".h\"" << endl; |
|
|
|
|
|
classInfo.printDefinition(cout); |
|
|
} catch (XmlRpcFault const& fault) { |
|
|
throw(logic_error("Failed to generate definition for class " + |
|
|
className + ". " + fault.getFaultString())); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int |
|
|
main(int const argc, |
|
|
const char ** const argv) { |
|
|
|
|
|
string const progName(argv[0]); |
|
|
|
|
|
cmdlineInfo const cmdline(argc, argv); |
|
|
|
|
|
int retval; |
|
|
|
|
|
XmlRpcClient::Initialize(NAME, VERSION); |
|
|
|
|
|
try { |
|
|
XmlRpcClass system = getClassInfo(cmdline.serverUrl, |
|
|
cmdline.methodPrefix, |
|
|
cmdline.localClass); |
|
|
printHeader(cout, system); |
|
|
cout << endl; |
|
|
printCppFile(cout, system); |
|
|
retval = 0; |
|
|
} catch (XmlRpcFault& fault) { |
|
|
cerr << progName << ": XML-RPC fault #" << fault.getFaultCode() |
|
|
<< ": " << fault.getFaultString() << endl; |
|
|
retval = 1; |
|
|
} catch (logic_error& err) { |
|
|
cerr << progName << ": " << err.what() << endl; |
|
|
retval = 1; |
|
|
} catch (...) { |
|
|
cerr << progName << ": Unknown exception" << endl; |
|
|
retval = 1; |
|
|
} |
|
|
|
|
|
XmlRpcClient::Terminate(); |
|
|
|
|
|
return retval; |
|
|
} |
|
|
|
|
|
|