CppCMS
|
00001 00002 // 00003 // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> 00004 // 00005 // See accompanying file COPYING.TXT file for licensing details. 00006 // 00008 #ifndef CPPCMS_RPC_JSON_OBJECT_H 00009 #define CPPCMS_RPC_JSON_OBJECT_H 00010 00011 #include <cppcms/application.h> 00012 #include <booster/function.h> 00013 #include <cppcms/json.h> 00014 #include <cppcms/cppcms_error.h> 00015 00016 namespace cppcms { 00020 namespace rpc { 00021 00029 class CPPCMS_API call_error : public cppcms_error { 00030 public: 00034 call_error(std::string const &message); 00035 }; 00036 00037 class json_rpc_server; 00038 00046 class CPPCMS_API json_call : public booster::noncopyable { 00047 public: 00048 00052 ~json_call(); 00053 00057 std::string method(); 00058 00066 bool notification(); 00067 00071 json::array const ¶ms(); 00072 00077 http::context &context(); 00078 00082 void return_result(json::value const &); 00086 void return_error(json::value const &); 00087 00088 private: 00089 00090 00091 json_call(http::context &context); 00092 friend class json_rpc_server; 00093 void return_result(http::context &,json::value const &); 00094 void return_error(http::context &,json::value const &); 00095 void attach_context(booster::shared_ptr<http::context> context); 00096 00097 void check_not_notification(); 00098 booster::shared_ptr<http::context> context_; 00099 json::value id_; 00100 json::array params_; 00101 std::string method_; 00102 bool notification_; 00103 00104 struct _data; 00105 booster::hold_ptr<_data> d; 00106 }; 00107 00114 class CPPCMS_API json_rpc_server : public application { 00115 public: 00119 typedef enum { 00120 any_role, 00121 method_role, 00122 notification_role 00123 } role_type; 00124 00128 typedef booster::function<void(json::array const &)> method_type; 00129 00133 void bind(std::string const &name,method_type const &,role_type type = any_role); 00134 00138 void smd(json::value const &); 00139 00143 void smd_raw(std::string const &); 00147 void smd_from_file(std::string const &); 00148 00152 virtual void main(std::string); 00153 00158 booster::shared_ptr<json_call> release_call(); 00159 00160 json_rpc_server(cppcms::service &srv); 00161 ~json_rpc_server(); 00162 00163 00167 std::string method(); 00175 bool notification(); 00179 json::array const ¶ms(); 00183 void return_result(json::value const &); 00187 void return_error(json::value const &); 00188 private: 00189 void check_call(); 00190 struct method_data { 00191 method_type method; 00192 role_type role; 00193 }; 00194 typedef std::map<std::string,method_data> methods_map_type; 00195 methods_map_type methods_; 00196 booster::shared_ptr<json_call> current_call_; 00197 00198 std::string smd_; 00199 00200 struct _data; 00201 booster::hold_ptr<_data> d; 00202 }; 00203 00205 00206 namespace details { 00207 00208 template<typename T> struct fw_ret { typedef T type; }; 00209 template<typename T> struct fw_ret<T const &> { typedef T type; }; 00210 template<typename T> struct fw_ret<T const> { typedef T type; }; 00211 00212 template<> struct fw_ret<json::value> { typedef json::value const &type; }; 00213 template<> struct fw_ret<json::object> { typedef json::object const &type; }; 00214 template<> struct fw_ret<json::array> { typedef json::array const &type; }; 00215 template<> struct fw_ret<std::string> { typedef std::string const &type; }; 00216 00217 template<> struct fw_ret<json::value const &> { typedef json::value const &type; }; 00218 template<> struct fw_ret<json::object const &> { typedef json::object const &type; }; 00219 template<> struct fw_ret<json::array const &> { typedef json::array const &type; }; 00220 template<> struct fw_ret<std::string const &> { typedef std::string const &type; }; 00221 00222 template<> struct fw_ret<json::value const> { typedef json::value const &type; }; 00223 template<> struct fw_ret<json::object const> { typedef json::object const &type; }; 00224 template<> struct fw_ret<json::array const> { typedef json::array const &type; }; 00225 template<> struct fw_ret<std::string const> { typedef std::string const &type; }; 00226 00227 00228 template<typename T> 00229 struct fw_ret_handle { 00230 static typename fw_ret<T>::type extract(json::value const &v) 00231 { 00232 return v.get_value<typename fw_ret<T>::type>(); 00233 } 00234 }; 00235 00236 template<> 00237 struct fw_ret_handle<json::value const &> 00238 { 00239 static json::value const &extract(json::value const &v) 00240 { 00241 return v; 00242 } 00243 }; 00244 00245 template<> 00246 struct fw_ret_handle<json::array const &> 00247 { 00248 static json::array const &extract(json::value const &v) 00249 { 00250 return v.array(); 00251 } 00252 }; 00253 00254 template<> 00255 struct fw_ret_handle<json::object const &> 00256 { 00257 static json::object const &extract(json::value const &v) 00258 { 00259 return v.object(); 00260 } 00261 }; 00262 00263 template<> 00264 struct fw_ret_handle<std::string const &> 00265 { 00266 static std::string const &extract(json::value const &v) 00267 { 00268 return v.str(); 00269 } 00270 }; 00271 00272 00273 template <typename T> 00274 inline typename fw_ret<T>::type forward_value(json::value const &v) 00275 { 00276 typedef typename fw_ret<T>::type return_type; 00277 return fw_ret_handle<return_type>::extract(v); 00278 } 00279 00280 } 00281 00282 #define CPPCMS_JSON_RPC_BINDER(N) \ 00283 namespace details { \ 00284 template<typename Class,typename Ptr CPPCMS_TEMPLATE_PARAMS> \ 00285 struct binder##N { \ 00286 Ptr object; \ 00287 void (Class::*member)(CPPCMS_FUNC_PARAMS); \ 00288 void operator()(json::array const &a) const \ 00289 { \ 00290 if(a.size()!=N) \ 00291 throw call_error("Invalid parametres number"); \ 00292 ((*object).*member)(CPPCMS_CALL_PARAMS); \ 00293 } \ 00294 }; \ 00295 } \ 00296 template<typename Class,typename Ptr CPPCMS_TEMPLATE_PARAMS> \ 00297 details::binder##N<Class,Ptr CPPCMS_BINDER_PARAMS> \ 00298 json_method(void (Class::*m)(CPPCMS_FUNC_PARAMS),Ptr p) \ 00299 { details::binder##N<Class,Ptr CPPCMS_BINDER_PARAMS> tmp={p,m}; return tmp; } \ 00300 00301 #define CPPCMS_TEMPLATE_PARAMS 00302 #define CPPCMS_FUNC_PARAMS 00303 #define CPPCMS_CALL_PARAMS 00304 #define CPPCMS_BINDER_PARAMS 00305 CPPCMS_JSON_RPC_BINDER(0) 00306 #undef CPPCMS_TEMPLATE_PARAMS 00307 #undef CPPCMS_FUNC_PARAMS 00308 #undef CPPCMS_CALL_PARAMS 00309 #undef CPPCMS_BINDER_PARAMS 00310 00311 #define CPPCMS_TEMPLATE_PARAMS ,typename P1 00312 #define CPPCMS_FUNC_PARAMS P1 00313 #define CPPCMS_CALL_PARAMS forward_value<P1>(a[0]) 00314 #define CPPCMS_BINDER_PARAMS ,P1 00315 CPPCMS_JSON_RPC_BINDER(1) 00316 #undef CPPCMS_TEMPLATE_PARAMS 00317 #undef CPPCMS_FUNC_PARAMS 00318 #undef CPPCMS_CALL_PARAMS 00319 #undef CPPCMS_BINDER_PARAMS 00320 00321 #define CPPCMS_TEMPLATE_PARAMS ,typename P1,typename P2 00322 #define CPPCMS_FUNC_PARAMS P1,P2 00323 #define CPPCMS_CALL_PARAMS forward_value<P1>(a[0]), forward_value<P2>(a[1]) 00324 #define CPPCMS_BINDER_PARAMS ,P1,P2 00325 CPPCMS_JSON_RPC_BINDER(2) 00326 #undef CPPCMS_TEMPLATE_PARAMS 00327 #undef CPPCMS_FUNC_PARAMS 00328 #undef CPPCMS_CALL_PARAMS 00329 #undef CPPCMS_BINDER_PARAMS 00330 00331 #define CPPCMS_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3 00332 #define CPPCMS_FUNC_PARAMS P1,P2,P3 00333 #define CPPCMS_CALL_PARAMS forward_value<P1>(a[0]), forward_value<P2>(a[1]), forward_value<P3>(a[2]) 00334 #define CPPCMS_BINDER_PARAMS ,P1,P2,P3 00335 CPPCMS_JSON_RPC_BINDER(3) 00336 #undef CPPCMS_TEMPLATE_PARAMS 00337 #undef CPPCMS_FUNC_PARAMS 00338 #undef CPPCMS_CALL_PARAMS 00339 #undef CPPCMS_BINDER_PARAMS 00340 00341 #define CPPCMS_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3,typename P4 00342 #define CPPCMS_FUNC_PARAMS P1,P2,P3,P4 00343 #define CPPCMS_CALL_PARAMS forward_value<P1>(a[0]), forward_value<P2>(a[1]), forward_value<P3>(a[2]), forward_value<P4>(a[3]) 00344 #define CPPCMS_BINDER_PARAMS ,P1,P2,P3,P4 00345 CPPCMS_JSON_RPC_BINDER(4) 00346 #undef CPPCMS_TEMPLATE_PARAMS 00347 #undef CPPCMS_FUNC_PARAMS 00348 #undef CPPCMS_CALL_PARAMS 00349 #undef CPPCMS_BINDER_PARAMS 00350 00351 #undef CPPCMS_JSON_RPC_BINDER 00352 00354 00355 } // rpc 00356 } // cppcms 00357 00358 00359 00360 #endif