00001
00002
00003
00004
00005
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 }
00356 }
00357
00358
00359
00360 #endif