1 /***************************************************************************
2         GenClientMethod.cpp  -  generate class with client methods
3                              -------------------
4     begin                : Thu Juk 19 2007
5     copyright            : (C) 2002-2007 by Ewald Arnold
6     email                : ulxmlrpcpp@ewald-arnold.de
7 
8     $Id: GenClientFunction.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 "GenClientFunction.h"
31 
32 #include <fstream>
33 #include <iostream>
34 
35 #include <sys/stat.h>
36 
37 
GenerateClientFunctions(const std::vector<Method> & methods)38 GenerateClientFunctions::GenerateClientFunctions(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 GenerateClientFunctions::generate_H(const std::string &destdir, const std::string &name)
46 {
47   const std::string h_name = destdir + name + "_ulxr_client.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 + "UlxrClient");
52   generateHeaderMethods(h_file, name);
53   h_file << "#endif // " << name + "UlxrClient" + "_H\n\n";
54 }
55 
56 
generate_CPP(const std::string & destdir,const std::string & name)57 void GenerateClientFunctions::generate_CPP(const std::string &destdir, const std::string &name)
58 {
59   const std::string h_name = name + "_ulxr_client.h";
60   const std::string cpp_name = destdir + name + "_ulxr_client.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(destdir, cpp_file, name);
66 }
67 
68 
generate_CPP_USER(const std::string & destdir,const std::string & name)69 void GenerateClientFunctions::generate_CPP_USER(const std::string &destdir, const std::string &name)
70 {
71   const std::string h_name = name + "_ulxr_client.h";
72   std::string cpp_name = destdir + name + "_ulxr_client_user.cpp";
73 
74   struct stat statbuf;
75   if (stat(cpp_name.c_str(), &statbuf) >= 0)
76   {
77     std::cout << "User file already exists: " << cpp_name << std::endl;
78     cpp_name += ".new";
79     std::cout << "New template will be created: " << cpp_name << std::endl;
80   }
81 
82   std::ofstream cpp_file(cpp_name.c_str());
83   std::cout << "User file will be created: " << cpp_name << std::endl;
84 
85   generateUserSourceHead(cpp_file, h_name);
86 
87   cpp_file << "// #include <ulxmlrpcpp/ulxr_response.h>\n";
88   cpp_file << "// #include <ulxmlrpcpp/ulxr_requester.h>\n";
89   cpp_file << "// #include <ulxmlrpcpp/ulxr_except.h>\n\n";
90 
91   cpp_file << "// #include \"" << name + "_ulxr_names.h" << "\"\n\n";
92 }
93 
94 
generate(const std::string & destdir,const std::string & name)95 void GenerateClientFunctions::generate(const std::string &destdir, const std::string &name)
96 {
97   generate_NameDefines(destdir, name, theMethods, name + "_");
98   generate_H(destdir, name);
99   generate_CPP(destdir, name);
100   generate_CPP_USER(destdir, name);
101 }
102 
103 
generateHeaderMethods(std::ostream & h_file,const std::string & name)104 void GenerateClientFunctions::generateHeaderMethods(std::ostream & h_file,
105                                                     const std::string &name)
106 {
107   h_file << "namespace ulxr\n"
108             "{\n"
109             "  class Requester;\n"
110             "}\n\n";
111 
112   for (unsigned i = 0; i < theMethods.size(); ++i)
113   {
114     Method method = theMethods[i];
115     std::string nspart = method.extractNamespace();
116     if (nspart.length() != 0)
117       h_file << "namespace " << nspart << " {\n";
118 
119     h_file << "// mapped to " << method.getOverloadName();
120     if (method.getName() != method.getOverloadName())
121       h_file << " (there are overloaded methods)";
122 
123     h_file << "\n" << method.getCppString(0, false, "") << "\n";
124 
125     if (nspart.length() != 0)
126       h_file << "}\n";
127     h_file << "\n";
128   }
129 
130   h_file << "void "
131          << name << "_setClientCredentials\n"
132          << "  (ulxr::Requester &in_requester, const ulxr::CppString &realm,\n"
133               "   const ulxr::CppString &user, const ulxr::CppString &pass);\n\n";
134 }
135 
136 
generateSourceMethods(const std::string & destdir,std::ostream & cpp_file,const std::string & name)137 void GenerateClientFunctions::generateSourceMethods(const std::string &destdir,
138                                                     std::ostream & cpp_file,
139                                                     const std::string &name)
140 {
141   cpp_file << "#include <ulxmlrpcpp/ulxr_response.h>\n";
142   cpp_file << "#include <ulxmlrpcpp/ulxr_requester.h>\n";
143   cpp_file << "#include <ulxmlrpcpp/ulxr_except.h>\n\n";
144 
145   cpp_file << "#include <memory>\n";
146   cpp_file << "#include <cassert>\n\n";
147 
148   cpp_file << "#include \"" << name + "_ulxr_names.h" << "\"\n\n";
149 
150   cpp_file << "namespace {\n\n"
151 
152            << "ulxr::Requester *requester = 0;\n"
153               "ulxr::CppString  rpc_realm;\n"
154               "ulxr::CppString  rpc_user;\n"
155               "ulxr::CppString  rpc_pass;\n\n"
156 
157            << "ulxr::MethodResponse\n  "
158            << "sendCall(const ulxr::MethodCall &calldata)\n"
159            << "{\n"
160            << "  assert(requester != 0);\n"
161            << "  ulxr::MethodResponse resp = requester->call(calldata, rpc_realm, rpc_user, rpc_pass);\n"
162            << "\n"
163            << "  if (!resp.isOK())\n"
164            << "  {\n"
165            << "    ulxr::Struct st = resp.getResult();\n"
166            << "    int ec = ulxr::Integer(st.getMember(ULXR_PCHAR(\"faultCode\"))).getInteger();\n"
167            << "    ulxr::CppString es = ulxr::RpcString(st.getMember(ULXR_PCHAR(\"faultString\"))).getString();\n"
168            << "    throw ulxr::RuntimeException(ec, es);\n"
169            << "  }\n"
170            << "\n"
171            << "  return resp;\n"
172            << "}\n\n";
173 
174 
175   for (unsigned i = 0; i < theMethods.size(); ++i)
176   {
177     const Method &method = theMethods[i];
178     const bool reftype = method.getType().isReference();
179     const bool ptrtype = method.getType().isPointer();
180     if (reftype || ptrtype)
181       cpp_file << method.getType().getProxyType() << " ulxr_refFor_" << name << method.getOverloadName() << ";\n";
182   }
183 
184   for (unsigned i = 0; i < theMethods.size(); ++i)
185   {
186     const Method &method = theMethods[i];
187 
188     cpp_file << "ulxr::MethodCall callTo_" << method.getOverloadName()
189              << "(ULXR_CALLTO_" << name << "_" << method.getOverloadName(false, "", "_")
190              << ");  // mapped to: " << method.getCppString(0, true, "");
191 
192     if (method.getName() != method.getOverloadName())
193        cpp_file << " (there are overloaded methods)";
194 
195     cpp_file << "\n";
196   }
197 
198   cpp_file << "\n} // namespace\n\n\n"
199            << "void " << name << "_setClientCredentials\n"
200            << "  (ulxr::Requester &in_requester, const ulxr::CppString &realm,\n"
201               "   const ulxr::CppString &user, const ulxr::CppString &pass)\n"
202               "{\n"
203               "  requester = &in_requester;\n"
204               "  rpc_realm = realm;\n"
205               "  rpc_user = user;\n"
206               "  rpc_pass = pass;\n"
207               "}\n\n";
208 
209   for (unsigned i = 0; i < theMethods.size(); ++i)
210   {
211     Method method = theMethods[i];
212     std::string nspart = method.extractNamespace();
213     if (nspart.length() != 0)
214       cpp_file << "namespace " << nspart << " {\n\n";
215 
216     cpp_file << "// mapped to " << method.getOverloadName(false);
217     if (method.getName() != method.getOverloadName())
218       cpp_file << " (there are overloaded methods)";
219 
220     cpp_file << "\n"
221              << method.getCppString(0, true, "") << "\n"
222              << "{\n";
223 
224     cpp_file << "  callTo_" << method.getOverloadName() << ".clear();\n";
225 
226     for (unsigned iarg = 0; iarg < method.numArgs(); ++iarg)
227     {
228       std::string adap = method.getArg(iarg).getType().getInversTypeAdapter();
229       std::string adap2;
230       if (adap.length() != 0)
231       {
232         adap += "(";
233         adap2 = ")";
234       }
235 
236       cpp_file << "  callTo_" << method.getOverloadName() << ".addParam("
237                << method.getArg(iarg).getType().getRpcName() << "(" << adap
238                << method.getArg(iarg).getType().getTypeDereference() << method.getArg(iarg).getName()
239                << adap2
240                << "));\n";
241 
242     }
243 
244     bool have_retval = false;
245     if (method.getType().getName() != "void" || method.getType().getLeft() != "" || method.getType().getRight() != "")
246       have_retval = true;
247 
248     if (have_retval)
249       cpp_file << "  ulxr::MethodResponse resp = sendCall(callTo_" << method.getOverloadName() << ");\n";
250     else
251       cpp_file << "  sendCall(callTo_" << method.getOverloadName() << ");\n";
252 
253     if (have_retval)
254     {
255       std::string adap = method.getType().getTypeAdapter();
256       std::string adap2;
257       if (adap.length() != 0)
258       {
259         adap += "(";
260         adap2 = ")";
261       }
262 
263       const bool reftype = method.getType().isReference();
264       const bool ptrtype = method.getType().isPointer();
265       if (reftype || ptrtype)
266         cpp_file << "  ulxr_refFor_" << name
267                 << method.getOverloadName() << " = ";
268       else
269         cpp_file  << "  return ";
270 
271       cpp_file << "(" << method.getType().getProxyType() << ") "
272                << adap + method.getType().getRpcName() << "(resp.getResult())." << method.getType().getRpcAccessor()
273                << "()" << adap2 << ";\n";
274 
275       if (reftype)
276         cpp_file << "  return ulxr_refFor_" << name
277                 << method.getOverloadName() << ";\n";
278 
279       else if (ptrtype)
280       {
281         std::string acc = "&";
282         std::string acc2 = method.getType().getTypeAccessor();
283         if (acc2.length() != 0)
284          acc = "";
285 
286         cpp_file << "  return "
287                  << "(" << method.getType().getCppString() << ") "
288                  << acc << "ulxr_refFor_" << name
289                  << method.getOverloadName() << acc2 << ";\n";
290       }
291     }
292 
293     cpp_file << "}\n\n";
294 
295     if (nspart.length() != 0)
296       cpp_file << "}\n";
297     cpp_file << "\n";
298   }
299 }
300 
301