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