1 /*************************************************************************** 2 GenServerMethod.cpp - generate class with server methods 3 ------------------- 4 begin : Sun May 28 2007 5 copyright : (C) 2002-2007 by Ewald Arnold 6 email : Ulxr@ewald-arnold.de 7 8 $Id: GenServerMethod.cpp 1016 2007-07-22 15:03:44Z ewald-arnold $ 9 10 ***************************************************************************/ 11 12 /************************************************************************** 13 * 14 * This program is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU Lesser General Public License as 16 * published by the Free Software Foundation; either version 2 of the License, 17 * or (at your option) any later version. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * GNU General Public License for more details. 23 * 24 * You should have received a copy of the GNU Lesser General Public License 25 * along with this program; if not, write to the Free Software 26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 * 28 ***************************************************************************/ 29 30 #include "GenServerMethod.h" 31 32 #include <fstream> 33 #include <iostream> 34 35 #include <sys/stat.h> 36 37 38 GenerateServerMethods::GenerateServerMethods(const UlxrIdlClass &in_class) 39 : theClass(in_class) 40 { 41 theClass.resolveOverloaded(); 42 } 43 44 45 void GenerateServerMethods::generate_H(const std::string &destdir, const std::string &name) 46 { 47 const std::string h_name = destdir + theClass.getBaseName() + "_ulxr_server.h"; 48 std::ofstream h_file(h_name.c_str()); 49 std::cout << "Header file will be created: " << h_name << std::endl; 50 51 generateHeaderHead(h_file, name + "UlxrServer"); 52 generateHeaderClassHead(h_file, name); 53 generateHeaderMethods(h_file); 54 generateHeaderVariables(h_file); 55 generateHeaderTail(h_file, name + "UlxrServer"); 56 } 57 58 59 void GenerateServerMethods::generate_CPP(const std::string &destdir, const std::string &name) 60 { 61 const std::string h_name = theClass.getBaseName() + "_ulxr_server.h"; 62 const std::string cpp_name = destdir + theClass.getBaseName() + "_ulxr_server.cpp"; 63 std::ofstream cpp_file(cpp_name.c_str()); 64 std::cout << "Source file will be created: " << cpp_name << std::endl; 65 66 generateSourceHead(cpp_file, h_name); 67 generateSourceCtors(cpp_file, name); 68 generateSourceMethods(cpp_file); 69 } 70 71 72 void GenerateServerMethods::generate_CPP_USER(const std::string &destdir, const std::string &name) 73 { 74 const std::string h_name = theClass.getBaseName() + "_ulxr_server.h"; 75 std::string cpp_name = destdir + theClass.getBaseName() + "_ulxr_server_user.cpp"; 76 77 struct stat statbuf; 78 if (stat(cpp_name.c_str(), &statbuf) >= 0) 79 { 80 std::cout << "User file already exists: " << cpp_name << std::endl; 81 cpp_name += ".new"; 82 std::cout << "New template will be created: " << cpp_name << std::endl; 83 } 84 85 std::ofstream cpp_file(cpp_name.c_str()); 86 std::cout << "User file will be created: " << cpp_name << std::endl; 87 88 generateUserSourceHead(cpp_file, h_name); 89 90 cpp_file << "#include <ulxmlrpcpp/ulxr_response.h>\n"; 91 cpp_file << "#include <ulxmlrpcpp/ulxr_method_adder.h>\n"; 92 cpp_file << "#include <ulxmlrpcpp/ulxr_signature.h>\n\n"; 93 94 cpp_file << "#include \"" << theClass.getSource() << "\"\n"; 95 cpp_file << "#include \"" << name + "_ulxr_names.h" << "\"\n\n"; 96 97 cpp_file << 98 "\nvoid " << name << "Server::setupServerMethods()\n" 99 "{\n"; 100 101 for (unsigned i = 0; i < theClass.numMethods(); ++i) 102 { 103 if (i != 0) 104 cpp_file << "\n"; 105 106 Method method = theClass.getMethod(i); 107 method.extractNamespace(); 108 109 cpp_file << " // mapped to: " << method.getCppString(0, false, ""); 110 111 if (method.getName() != method.getOverloadName()) 112 cpp_file << " (there are overloaded methods)"; 113 114 cpp_file << 115 "\n" 116 " method_adder.addMethod(ulxr::make_method(*this, &" << method.getOverloadName(true, "Server") << "),\n" 117 " " << method.getType().getRpcName() << "::getValueName(),\n" 118 " ULXR_CALLTO_" << method.getOverloadName(true, "", "_") << ",\n" 119 " ulxr::Signature()"; 120 121 for (unsigned p = 0; p < method.numArgs(); ++p) 122 cpp_file << "\n << " << method.getArg(p).getType().getRpcName() << "::getValueName()"; 123 124 cpp_file << 125 ",\n" 126 " ulxr_i18n(ULXR_PCHAR(\"Some descriptive comment about '" << method.getCppString(0, true, "") << "'.\"))); // TODO adjust comment\n"; 127 } 128 129 cpp_file << 130 "}\n\n"; 131 } 132 133 134 void GenerateServerMethods::generate(const std::string &destdir, const std::string &name) 135 { 136 generate_NameDefines(destdir, theClass.getBaseName(), theClass.getAllMethods()); 137 generate_H(destdir, name); 138 generate_CPP(destdir, name); 139 generate_CPP_USER(destdir, name); 140 } 141 142 143 void GenerateServerMethods::generateHeaderMethods(std::ostream & h_file) 144 { 145 for (unsigned i = 0; i < theClass.numMethods(); ++i) 146 { 147 Method method = theClass.getMethod(i); 148 method.extractNamespace(); 149 150 h_file << " // mapped to: " << method.getCppString(0, false, ""); 151 152 if (method.getName() != method.getOverloadName()) 153 h_file << " (there are overloaded methods)"; 154 155 h_file << "\n" 156 << " ulxr::MethodResponse " << method.getOverloadName() << " (const ulxr::MethodCall &calldata);\n\n"; 157 } 158 159 h_file << " private:\n\n"; 160 h_file << " void setupServerMethods();\n"; 161 h_file << " void removeServerMethods();\n\n"; 162 } 163 164 165 void GenerateServerMethods::generateSourceCtors(std::ostream & cpp_file, 166 const std::string &name) 167 { 168 cpp_file << "#include <ulxmlrpcpp/ulxr_response.h>\n"; 169 cpp_file << "#include <ulxmlrpcpp/ulxr_call.h>\n"; 170 cpp_file << "#include <ulxmlrpcpp/ulxr_dispatcher.h>\n"; 171 cpp_file << "#include <ulxmlrpcpp/ulxr_value.h>\n\n"; 172 173 cpp_file << "#include \"" << theClass.getSource() << "\"\n\n\n"; 174 cpp_file << "#include \"" << name + "_ulxr_names.h" << "\"\n\n"; 175 176 cpp_file << name << "Server::" << name << "Server" 177 << "(ulxr::MethodAdder &in_method_adder, " << theClass.getName() << " &in_server)\n" 178 << " : server(in_server)\n" 179 " , method_adder(in_method_adder)\n"; 180 181 cpp_file << "{\n" 182 " setupServerMethods();\n" 183 "}\n\n\n"; 184 185 cpp_file << name << "Server::~" << name << "Server()\n" 186 << "{\n" 187 " removeServerMethods();\n" 188 "}\n\n\n"; 189 } 190 191 192 void GenerateServerMethods::generateSourceMethods(std::ostream & cpp_file) 193 { 194 for (unsigned i = 0; i < theClass.numMethods(); ++i) 195 { 196 Method method = theClass.getMethod(i); 197 method.extractNamespace(); 198 199 cpp_file << "// mapped to: " << method.getCppString(0, false, ""); 200 201 if (method.getName() != method.getOverloadName()) 202 cpp_file << " (there are overloaded methods)"; 203 204 cpp_file << "\nulxr::MethodResponse\n " 205 << method.getOverloadName(true, "Server") << " (const ulxr::MethodCall &calldata)\n" 206 << "{\n" 207 << " try\n" 208 << " {\n"; 209 210 for (unsigned iarg = 0; iarg < method.numArgs(); ++iarg) 211 { 212 std::string adap = method.getArg(iarg).getType().getTypeAdapter(); 213 std::string adap2; 214 if (adap.length() != 0) 215 { 216 adap += "("; 217 adap2 = ")"; 218 } 219 220 cpp_file << " " << method.getArg(iarg).getType().getName() << " p" << iarg << " = " 221 << "(" << method.getArg(iarg).getType().getName() << ") " 222 << adap + method.getArg(iarg).getType().getRpcName() << "(calldata.getParam(" << iarg << "))." << method.getArg(iarg).getType().getRpcAccessor() 223 << "()" << adap2 << ";\n"; 224 } 225 226 bool have_retval = false; 227 if (method.getType().getName() != "void" || method.getType().getLeft() != "" || method.getType().getRight() != "") 228 have_retval = true; 229 230 if (have_retval) 231 { 232 cpp_file << " " << method.getType().getProxyType() << " retval = " 233 << method.getType().getTypeDereference(); 234 } 235 else 236 cpp_file << " "; 237 238 cpp_file << "server." << method.getName() << "("; 239 240 for (unsigned iarg = 0; iarg < method.numArgs(); ++iarg) 241 { 242 if (iarg != 0) 243 cpp_file << ", "; 244 245 // cpp_file << "(" << method.getArg(iarg).getType().getCppString() << ")"; 246 247 if(method.getArg(iarg).getType().isPointer()) 248 cpp_file << "&"; 249 250 cpp_file << "p" << iarg; 251 } 252 253 cpp_file << ");\n"; 254 255 std::string adap = method.getType().getInversTypeAdapter(); 256 std::string adap2; 257 if (adap.length() != 0) 258 { 259 adap += "("; 260 adap2 = ")"; 261 } 262 263 if (have_retval) 264 cpp_file << " return ulxr::MethodResponse ("<< method.getType().getRpcName() << " (" << adap << "retval" << adap2 << "));\n"; 265 else 266 cpp_file << " return ulxr::MethodResponse (ulxr::Void());\n"; 267 268 cpp_file << " }\n" 269 << " catch(std::exception &ex)\n" 270 << " {\n" 271 << " ulxr::CppString s = ULXR_PCHAR(\"C++ exception caught when invoking '" << method.getCppString(0, false, "") << "'\\n \");\n" 272 << " s += ULXR_GET_STRING(ex.what());\n" 273 << " return ulxr::MethodResponse(ulxr::ApplicationError, s);\n" 274 << " }\n" 275 << " catch(...)\n" 276 << " {\n" 277 << " ulxr::CppString s = ULXR_PCHAR(\"Unknown exception caught when invoking '" << method.getCppString(0, false, "") << "'\");\n" 278 << " return ulxr::MethodResponse(ulxr::ApplicationError, s);\n" 279 << " }\n"; 280 281 cpp_file << "}\n\n\n"; 282 } 283 284 // ------------------------------------ 285 286 cpp_file << 287 "\nvoid " << theClass.getBaseName() << "Server::removeServerMethods()\n" 288 "{\n"; 289 290 for (unsigned i = 0; i < theClass.numMethods(); ++i) 291 { 292 Method method = theClass.getMethod(i); 293 method.extractNamespace(); 294 295 cpp_file << 296 " method_adder.removeMethod(ULXR_CALLTO_" << method.getOverloadName(true, "", "_") << ");"; 297 298 cpp_file << " // mapped to: " << method.getCppString(0, false, ""); 299 300 if (method.getName() != method.getOverloadName()) 301 cpp_file << " (there are overloaded methods)"; 302 303 cpp_file << "\n"; 304 } 305 306 cpp_file << "\n}\n\n\n"; 307 } 308 309 310 void GenerateServerMethods::generateHeaderClassHead(std::ostream & h_file, 311 const std::string &name) 312 { 313 std::string ns = theClass.getNamespace(); 314 if (ns.length() == 0) 315 h_file << "\n" 316 << "class " << name << ";\n\n"; 317 else 318 h_file << "namespace " << ns << "\n{\n" 319 << " class " << theClass.getBaseName() << ";\n" 320 << "}\n\n"; 321 322 h_file << "\nnamespace ulxr\n" 323 << "{\n" 324 << " class MethodAdder;\n" 325 << " class MethodCall;\n" 326 << " class MethodResponse;\n" 327 << "}\n\n" 328 << "class " << name << "Server\n" 329 << "{\n" 330 << " public:\n\n" 331 << " " << name << "Server(ulxr::MethodAdder &method_adder, " << theClass.getName() << " &server);\n\n" 332 << " ~" << name << "Server();\n\n"; 333 } 334 335 336 void GenerateServerMethods::generateHeaderVariables(std::ostream & h_file) 337 { 338 h_file << " private:\n\n"; 339 for (unsigned i = 0; i < theClass.numMethods(); ++i) 340 { 341 Method method = theClass.getMethod(i); 342 method.extractNamespace(); 343 344 const bool reftype = method.getType().isReference(); 345 if (reftype) 346 h_file << " mutable " << method.getType().getName() << " ulxr_refFor_" << method.getOverloadName() << ";\n"; 347 } 348 349 h_file << " " << theClass.getName() << " &server;\n" 350 << " ulxr::MethodAdder &method_adder;\n"; 351 } 352 353 354