1 /***************************************************************************
2         GenServerMethod.cpp  -  generate class with server methods
3                              -------------------
4     begin                : Thu Juk 19 2007
5     copyright            : (C) 2002-2007 by Ewald Arnold
6     email                : Ulxr@ewald-arnold.de
7 
8     $Id: GenServerFunction.cpp 1164 2010-01-06 10:03:51Z 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 "GenServerFunction.h"
31 
32 #include <fstream>
33 #include <iostream>
34 
35 #include <sys/stat.h>
36 
37 
GenerateServerFunctions(const std::vector<Method> & methods)38 GenerateServerFunctions::GenerateServerFunctions(const std::vector<Method> &methods)
39   : theMethods(methods)
40 {
41   Method::resolveOverloaded(theMethods);
42 }
43 
44 
generate_H(const std::string & destdir,const std::string & name)45 void GenerateServerFunctions::generate_H(const std::string &destdir, const std::string &name)
46 {
47   const std::string h_name = destdir + name + "_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   generateHeaderMethods(h_file, name);
53   h_file << "#endif // " << name + "UlxrServer" + "_H\n\n";
54 }
55 
56 
generate_CPP(const std::string & destdir,const std::string & name)57 void GenerateServerFunctions::generate_CPP(const std::string &destdir, const std::string &name)
58 {
59   const std::string h_name = name + "_ulxr_server.h";
60   const std::string cpp_name = destdir + name + "_ulxr_server.cpp";
61   std::ofstream cpp_file(cpp_name.c_str());
62   std::cout << "Source file will be created: " << cpp_name << std::endl;
63 
64   generateSourceHead(cpp_file, h_name);
65   generateSourceMethods(cpp_file, name);
66 }
67 
68 
generate_CPP_USER(const std::string & destdir,const std::string & name)69 void GenerateServerFunctions::generate_CPP_USER(const std::string &destdir,
70                                                 const std::string &name)
71 {
72   const std::string h_name = name + "_ulxr_server.h";
73   std::string cpp_name = destdir + name + "_ulxr_server_user.cpp";
74 
75   struct stat statbuf;
76   if (stat(cpp_name.c_str(), &statbuf) >= 0)
77   {
78     std::cout << "User file already exists: " << cpp_name << std::endl;
79     cpp_name += ".new";
80     std::cout << "New template will be created: " << cpp_name << std::endl;
81   }
82 
83   std::ofstream cpp_file(cpp_name.c_str());
84   std::cout << "User file will be created: " << cpp_name << std::endl;
85 
86   generateUserSourceHead(cpp_file, h_name);
87 
88   cpp_file << "#include <ulxmlrpcpp/ulxr_response.h>\n";
89   cpp_file << "#include <ulxmlrpcpp/ulxr_method_adder.h>\n";
90   cpp_file << "#include <ulxmlrpcpp/ulxr_signature.h>\n\n";
91 
92 //   if (theMethods.size() != 0)
93 //     cpp_file << "#include \"" << theMethods[0].getSource() << "\"\n";
94 
95   cpp_file << "#include \"" << name + "_ulxr_names.h" << "\"\n\n";
96 
97   for (unsigned i = 0; i < theMethods.size(); ++i)
98     cpp_file << "\nulxr::MethodResponse\n  "
99              << name << "_" << theMethods[i].getOverloadName(false) << " (const ulxr::MethodCall &calldata);\n";
100 
101   cpp_file <<
102     "\n\nvoid " << name << "_setupServerMethods(ulxr::MethodAdder &method_adder)\n"
103     "{\n";
104 
105   for (unsigned i = 0; i < theMethods.size(); ++i)
106   {
107     if (i != 0)
108       cpp_file << "\n";
109 
110     const Method &method = theMethods[i];
111 
112     cpp_file << "// mapped to: " << method.getCppString(0, false, "");
113 
114     if (method.getName() != method.getOverloadName())
115        cpp_file << "   (there are overloaded methods)";
116 
117     cpp_file <<
118       "\n"
119       "  method_adder.addMethod(ulxr::make_method(&" << name << "_" << method.getOverloadName(false) << "),\n"
120       "                         " << method.getType().getRpcName() << "::getValueName(),\n"
121       "                         ULXR_CALLTO_" << name << "_" << method.getOverloadName(false) << ",\n"
122       "                         ulxr::Signature()";
123 
124     for (unsigned p = 0; p < method.numArgs(); ++p)
125       cpp_file << "\n                           << " << method.getArg(p).getType().getRpcName() << "::getValueName()";
126 
127     cpp_file <<
128       ",\n"
129       "                         ulxr_i18n(ULXR_PCHAR(\"Some descriptive comment about '" << method.getCppString(0, true, "") << "'.\"))); // TODO adjust comment\n";
130   }
131 
132   cpp_file <<
133     "}\n\n";
134 }
135 
136 
generate(const std::string & destdir,const std::string & name)137 void GenerateServerFunctions::generate(const std::string &destdir, const std::string &name)
138 {
139   GenerateMethod::generate_NameDefines(destdir, name, theMethods, name + "_");
140   generate_H(destdir, name);
141   generate_CPP(destdir, name);
142   generate_CPP_USER(destdir, name);
143 }
144 
145 
generateHeaderMethods(std::ostream & h_file,const std::string & name)146 void GenerateServerFunctions::generateHeaderMethods(std::ostream & h_file,
147                                                     const std::string &name)
148 {
149   h_file << "namespace ulxr\n"
150          << "{\n"
151          << "  class MethodAdder;\n"
152          << "}\n\n";
153 
154   h_file << "void " << name << "_setupServerMethods(ulxr::MethodAdder &method_adder);\n\n";
155   h_file << "void " << name << "_removeServerMethods(ulxr::MethodAdder &method_adder);\n\n";
156 }
157 
158 
generateSourceMethods(std::ostream & cpp_file,const std::string & name)159 void GenerateServerFunctions::generateSourceMethods(std::ostream & cpp_file,
160                                                     const std::string &name)
161 {
162   cpp_file << "#include <ulxmlrpcpp/ulxr_response.h>\n";
163   cpp_file << "#include <ulxmlrpcpp/ulxr_requester.h>\n";
164   cpp_file << "#include <ulxmlrpcpp/ulxr_except.h>\n";
165   cpp_file << "#include <ulxmlrpcpp/ulxr_method_adder.h>\n\n";
166 
167   cpp_file << "#include \"" << name + "_ulxr_names.h" << "\"\n";
168 //  if (theMethods.size() != 0)
169     cpp_file << "#include \"" << theMethods[0].getSource() << "\"\n";
170 
171   cpp_file << "\n";
172 
173   for (unsigned i = 0; i < theMethods.size(); ++i)
174   {
175     const Method &method = theMethods[i];
176 
177     cpp_file << "// mapped to: " << method.getCppString(0, false, "");
178 
179     if (method.getName() != method.getOverloadName())
180        cpp_file << "   (there are overloaded methods)";
181 
182     cpp_file << "\nulxr::MethodResponse\n  "
183              << name << "_" << method.getOverloadName(false) << " (const ulxr::MethodCall &calldata)\n"
184              << "{\n"
185              << "  try\n"
186              << "  {\n";
187 
188     for (unsigned iarg = 0; iarg < method.numArgs(); ++iarg)
189     {
190       std::string adap = method.getArg(iarg).getType().getTypeAdapter();
191       std::string adap2;
192       if (adap.length() != 0)
193       {
194         adap += "(";
195         adap2 = ")";
196       }
197 
198       cpp_file << "    " << method.getArg(iarg).getType().getName() << " p" << iarg << " = "
199                << "(" << method.getArg(iarg).getType().getName() << ") "
200                << adap + method.getArg(iarg).getType().getRpcName() << "(calldata.getParam(" << iarg << "))." << method.getArg(iarg).getType().getRpcAccessor()
201                << "()" << adap2 << ";\n";
202     }
203 
204     bool have_retval = false;
205     if (method.getType().getName() != "void" || method.getType().getLeft() != "" || method.getType().getRight() != "")
206       have_retval = true;
207 
208     if (have_retval)
209     {
210       cpp_file << "    " << method.getType().getProxyType() << " retval = "
211                << method.getType().getTypeDereference();
212     }
213     else
214       cpp_file << "    ";
215 
216     cpp_file << method.getName() << "(";
217 
218     for (unsigned iarg = 0; iarg < method.numArgs(); ++iarg)
219     {
220       if (iarg != 0)
221         cpp_file << ", ";
222 
223 //      cpp_file << "(" << method.getArg(iarg).getType().getCppString() << ")";
224 
225       if(method.getArg(iarg).getType().isPointer())
226         cpp_file << "&";
227 
228       cpp_file  << "p" << iarg;
229     }
230 
231     cpp_file << ");\n";
232 
233     std::string adap = method.getType().getInversTypeAdapter();
234     std::string adap2;
235     if (adap.length() != 0)
236     {
237       adap += "(";
238       adap2 = ")";
239     }
240 
241     if (have_retval)
242       cpp_file << "    return ulxr::MethodResponse ("<< method.getType().getRpcName() << " (" <<  adap << "retval" << adap2 << "));\n";
243     else
244       cpp_file << "    return ulxr::MethodResponse (ulxr::Void());\n";
245 
246     cpp_file << "  }\n"
247              << "  catch(std::exception &ex)\n"
248              << "  {\n"
249              << "    ulxr::CppString s = ULXR_PCHAR(\"C++ exception caught when invoking '" << method.getCppString(0, false, "") << "'\\n  \");\n"
250              << "    s += ULXR_GET_STRING(ex.what());\n"
251              << "    return ulxr::MethodResponse(ulxr::ApplicationError, s);\n"
252              << "  }\n"
253              << "  catch(...)\n"
254              << "  {\n"
255              << "    ulxr::CppString s = ULXR_PCHAR(\"Unknown exception caught when invoking '" << method.getCppString(0, false, "") << "'\");\n"
256              << "    return ulxr::MethodResponse(ulxr::ApplicationError, s);\n"
257              << "  }\n";
258 
259     cpp_file << "}\n\n\n";
260   }
261 
262   // ------------------------------------
263 
264   cpp_file <<
265     "\nvoid " << name << "_removeServerMethods(ulxr::MethodAdder &method_adder)\n"
266     "{\n";
267 
268   for (unsigned i = 0; i < theMethods.size(); ++i)
269   {
270     const Method &method = theMethods[i];
271     cpp_file <<
272       "  method_adder.removeMethod(ULXR_CALLTO_" << name << "_" << method.getOverloadName(false, "", "_") << ");\n";
273   }
274 
275   cpp_file << "}\n\n";
276 }
277