freeswitch/libs/xmlrpc-c/tools/xml-rpc-api2cpp/xml-rpc-api2cpp.cpp

213 lines
6.3 KiB
C++

#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"
/*----------------------------------------------------------------------------
Command line
-----------------------------------------------------------------------------*/
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) {
/*----------------------------------------------------------------------------
Connect to a remote server and extract the information we'll need to
build a proxy class.
-----------------------------------------------------------------------------*/
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) {
// Break the method name into two pieces.
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) {
// It's a method User cares about
string const help(system.methodHelp(methodName));
XmlRpcValue const signatureList(
system.methodSignature(methodName));
if (signatureList.getType() != XMLRPC_TYPE_ARRAY) {
// It must be the string "undef", meaning the server
// won't tell us any signatures.
cerr << "Skipping method " << methodName << " "
<< "because server does not report any signatures "
<< "for it (via system.methodSignature method)"
<< endl;
} else {
// Add this function to our class information.
XmlRpcFunction const method(functionName,
methodName,
help,
signatureList);
info.addFunction(method);
}
}
}
return info;
}
static void
printHeader(ostream & out,
XmlRpcClass const& classInfo) {
/*----------------------------------------------------------------------------
Print a complete header for the specified class.
-----------------------------------------------------------------------------*/
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) {
/*----------------------------------------------------------------------------
Print a complete definition for the specified class.
-----------------------------------------------------------------------------*/
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;
}