Savarese Software Research Corporation
ws/protocol.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2009 Savarese Software Research Corporation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     https://www.savarese.com/software/ApacheLicense-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00022 #ifndef __SSRC_WSPR_WS_PROTOCOL_H
00023 #define __SSRC_WSPR_WS_PROTOCOL_H
00024 
00025 #include <ssrc/wispers/protocol.h>
00026 #include <ssrc/wispers/fcgi/parameter_map.h>
00027 #include <ssrc/wispers/session/protocol.h>
00028 #include <ssrc/wispers/utility/StringTo.h>
00029 #include <ssrc/wispers/utility/AppendToContainer.h>
00030 
00031 #include <boost/preprocessor/stringize.hpp>
00032 
00033 #ifdef WSPR_DEBUG
00034 #include <iostream>
00035 #endif
00036 
00037 __BEGIN_NS_SSRC_WSPR_PROTOCOL
00038 
00039 WSPR_DEFINE_PROTOCOL(WebService,ws);
00040 
00041 __END_NS_SSRC_WSPR_PROTOCOL
00042 
00043 __BEGIN_NS_SSRC_WSPR_WS
00044 
00045 using std::string;
00046 using NS_SSRC_WISP_PROTOCOL::wisp_call_token;
00047 using NS_SSRC_WISP_PROTOCOL::MessageInfo;
00048 using NS_SSRC_WSPR_UTILITY::Properties;
00049 using NS_SSRC_WSPR_UTILITY::property_vector;
00050 using NS_SSRC_WSPR_UTILITY::properties_ptr;
00051 using NS_SSRC_WSPR_UTILITY::properties_unique_ptr;
00052 using NS_SSRC_WSPR_UTILITY::AppendToContainer;
00053 using NS_SSRC_WSPR_SESSION::session_ptr;
00054 
00056 #define WSPR_WS_TYPE(service_base_str) "wspr.ws." service_base_str
00057 
00058 inline Properties & set_web_event_header(Properties & properties,
00059                                          const string & protocol,
00060                                          const string & call)
00061 {
00062   properties.set(protocol, "protocol");
00063   properties.set(call, "call");
00064   return properties;
00065 }
00066 
00067 inline Properties & set_web_event_header(Properties & properties,
00068                                          const string & protocol,
00069                                          const string & call,
00070                                          const gsid_type gsid)
00071 {
00072   properties.set(gsid, "gsid");
00073   return set_web_event_header(properties, protocol, call);
00074 }
00075 
00076 inline properties_unique_ptr
00077 web_event(const string & protocol, const string & call) {
00078   properties_unique_ptr props(new Properties);
00079   set_web_event_header(*props, protocol, call);
00080   return props;
00081 }
00082 
00083 inline properties_unique_ptr
00084 web_event(const string & protocol, const string & call, const gsid_type gsid) {
00085   properties_unique_ptr props(new Properties);
00086   set_web_event_header(*props, protocol, call, gsid);
00087   return props;
00088 }
00089 
00090 inline Properties & web_event_indirect(Properties & properties,
00091                                        const string & protocol,
00092                                        const string & call)
00093 {
00094   return set_web_event_header(properties, protocol, call);
00095 }
00096 
00097 inline Properties & web_event_indirect(Properties & properties,
00098                                        const string & protocol,
00099                                        const string & call,
00100                                        const gsid_type gsid)
00101 {
00102   return set_web_event_header(properties, protocol, call, gsid);
00103 }
00104 
00105 inline Properties & web_event_direct(Properties & properties,
00106                                      const string & protocol,
00107                                      const string & call)
00108 {
00109   Properties *node;
00110   property_vector & v = properties.create_property_vector("wspr", "event");
00111   v.push_back(node = new Properties);
00112   return set_web_event_header(*node, protocol, call);
00113 }
00114 
00115 inline Properties & web_event_direct(Properties & properties,
00116                                      const string & protocol,
00117                                      const string & call,
00118                                      const gsid_type gsid)
00119 {
00120   Properties *node;
00121   property_vector & v = properties.create_property_vector("wspr", "event");
00122   v.push_back(node = new Properties);
00123   return set_web_event_header(*node, protocol, call, gsid);
00124 }
00125 
00126 struct WebServiceCall {
00127   WISP_IMPORT(NS_SSRC_WSPR_FCGI, parameter_map);
00128   string call;
00129   parameter_map parameters;
00130   session_ptr session;
00131 
00132   WebServiceCall() { }
00133 
00134   WebServiceCall(const string & call,
00135              const parameter_map & parameters,
00136              const session_ptr & session = session_ptr()) :
00137     call(call), parameters(parameters), session(session)
00138   { }
00139 
00140   bool is_parameter(const string & param_name) const {
00141     parameter_map::const_iterator && it = parameters.find(param_name);
00142 
00143     if(it == parameters.end())
00144       return false;
00145 
00146     return true;
00147   }
00148 
00149   template<typename param_type>
00150   bool get_parameter(const string & param_name, param_type & value) const
00151     SSRC_DECL_THROW(std::bad_cast)
00152   {
00153     parameter_map::const_iterator && it = parameters.find(param_name);
00154 
00155     if(it == parameters.end())
00156       return false;
00157 
00158     value = utility::string_to<param_type>(it->second);
00159 
00160     return true;
00161   }
00162 
00163   template<typename param_type>
00164   param_type get_parameter(const string & param_name) const
00165     SSRC_DECL_THROW(std::bad_cast)
00166   {
00167     parameter_map::const_iterator && it = parameters.find(param_name);
00168 
00169     if(it == parameters.end())
00170       return param_type();
00171 
00172     return utility::string_to<param_type>(it->second);
00173   }
00174 
00175 
00176   template<typename container_type>
00177   unsigned int get_parameters(const string & param_name,
00178                               container_type & container) const
00179     SSRC_DECL_THROW(std::bad_cast)
00180   {
00181     WISP_IMPORT_T(container_type, value_type);
00182     unsigned int count(0);
00183     std::pair<parameter_map::const_iterator,parameter_map::const_iterator> &&
00184       range = parameters.equal_range(param_name);
00185     AppendToContainer<container_type> append(container);
00186 
00187     while(range.first != range.second) {
00188       append(utility::string_to<value_type>(range.first->second));
00189       ++range.first;
00190       ++count;
00191     }
00192 
00193     return count;
00194   }
00195 
00196   template<class Archive>
00197   void serialize(Archive & ar, const unsigned int) {
00198     ar & call & parameters & session;
00199   }
00200 };
00201 
00202 template<> inline
00203 bool WebServiceCall::get_parameter<string>(const string & param_name,
00204                                            string & value) const 
00205 {
00206   parameter_map::const_iterator && it = parameters.find(param_name);
00207 
00208   if(it == parameters.end())
00209     return false;
00210 
00211   value = it->second;
00212 
00213   return true;
00214 }
00215 
00216 template<> inline
00217 string WebServiceCall::get_parameter<string>(const string & param_name) const {
00218   parameter_map::const_iterator && it = parameters.find(param_name);
00219 
00220   if(it == parameters.end())
00221     return string();
00222 
00223   return it->second;
00224 }
00225 
00226 #define __WS_DEFINE_CALL_PARAM(r, data, arg) \
00227   BOOST_PP_TUPLE_ELEM(2, 0, arg) BOOST_PP_TUPLE_ELEM(2, 1, arg);
00228 
00229 #define __WS_INIT_CALL_PARAM(r, data, i, arg)                          \
00230   BOOST_PP_COMMA_IF(i)  BOOST_PP_TUPLE_ELEM(2, 1, arg)(call . get_parameter<BOOST_PP_TUPLE_ELEM(2, 0, arg)>(BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, arg))))
00231 // This is for the benefit of client code that wants to define its own
00232 // macros that add extra functionality to the generated structure.
00233 #define __WS_CALL_PARAM(name, param_sequence) \
00234     BOOST_PP_SEQ_FOR_EACH(__WS_DEFINE_CALL_PARAM, _, param_sequence)  \
00235       name (const NS_SSRC_WSPR_WS::WebServiceCall & call) SSRC_DECL_THROW(std::bad_cast) : \
00236       BOOST_PP_SEQ_FOR_EACH_I(__WS_INIT_CALL_PARAM, call, param_sequence) \
00237       { }                                                               \
00238 
00239 #define WS_CALL_PARAM(name, param_sequence)                         \
00240   struct name {                                                         \
00241     __WS_CALL_PARAM(name, param_sequence)                           \
00242   }
00243 
00244 template<typename ws_type, typename param_type> inline
00245 void ws_call(ws_type * impl,
00246              void (ws_type::* call_handler)(const WebServiceCall &, const param_type &, const MessageInfo &),
00247              const WebServiceCall & call,
00248              const MessageInfo & msginfo)
00249 {
00250 #ifdef WSPR_DEBUG
00251   try {
00252 #endif
00253     (impl->*call_handler)(call, param_type(call), msginfo);
00254 #ifdef WSPR_DEBUG
00255   } catch(const std::bad_cast & blc) {
00256     // TODO: log
00257     std::cerr << "bad parameters for " << call.call << std::endl
00258               << blc.what() << std::endl;
00259     for(WebServiceCall::parameter_map::const_iterator it = call.parameters.begin();
00260         it != call.parameters.end(); ++it)
00261     {
00262       std::cerr << it->first << " : " << it->second << std::endl;
00263     }
00264     throw;
00265   }
00266 #endif
00267 }
00268 
00269 struct WebServiceProtocol :
00270   public protocol::ServiceProtocol<protocol::WebService>
00271 {
00272   WISP_IMPORT(NS_SSRC_WSPR_FCGI, parameter_map);
00273 
00274   enum MessageType {
00275     OneWay,
00276     TwoWay,
00277     Response,
00278     DeliverEvent,
00279     DeliverEvents
00280   };
00281 
00282   template<MessageType type>
00283   struct MessageCallBase : public protocol::MessageWebService<type> {
00284     WebServiceCall call;
00285 
00286     MessageCallBase() { }
00287 
00288     MessageCallBase(const string & call,
00289                     const parameter_map & parameters,
00290                     const session_ptr & session = session_ptr()) :
00291       call(call, parameters, session)
00292     { }
00293 
00294     template<class Archive>
00295     void serialize(Archive & ar, const unsigned int) {
00296       ar & call;
00297     }
00298   };
00299 
00300   typedef MessageCallBase<OneWay> MessageOneWay;
00301   typedef MessageCallBase<TwoWay> MessageTwoWay;
00302 
00303   // IMPORTANT: Changes to MessageResponse must be reflected in SWIG binding.
00304   // SWIG does not automatically handle nested classes, so we have a separate
00305   // SWIG interface that must be synchronized to this definition.
00306   class MessageResponse : public protocol::MessageWebService<Response> {
00307     enum Status { Succeeded, Failed, Error };
00308 
00309     unsigned int status;
00310     string status_msg;
00311 
00312     void set_status(Status s, const string & msg) {
00313       status = s;
00314       status_msg = msg;
00315     }
00316 
00317   public:
00318     session_ptr session;
00319     properties_ptr template_data;
00320 
00321     explicit MessageResponse(const session_ptr & session = session_ptr()) :
00322       status(Succeeded), status_msg(), session(session),
00323       template_data(new Properties)
00324     { }
00325 
00326     // template_data must be the result of new Properties or 0.
00327     explicit MessageResponse(const session_ptr & session,
00328                              Properties * template_data) :
00329       status(Succeeded), status_msg(), session(session),
00330       template_data(template_data)
00331     { }
00332 
00333     explicit MessageResponse(const session_ptr & session,
00334                              const properties_ptr & template_data) :
00335       status(Succeeded), status_msg(), session(session),
00336       template_data(template_data)
00337     { }
00338 
00339     void set_succeeded(const string & msg = ""){
00340       set_status(Succeeded, msg);
00341     }
00342 
00343     void set_failed(const string & msg = "") {
00344       set_status(Failed, msg);
00345     }
00346 
00347     void set_error(const string & msg = "") {
00348       set_status(Error, msg);
00349     }
00350 
00351     bool succeeded() const { return (status == Succeeded); }
00352 
00353     bool failed() const { return (status == Failed); }
00354 
00355     bool error() const { return (status == Error); }
00356 
00357     const string & status_message() const { return status_msg; }
00358 
00359     template<class Archive>
00360     void serialize(Archive & ar, const unsigned int) {
00361       ar & status & status_msg & session & template_data;
00362     }
00363   };
00364 
00365 
00366   // This is for the EventQueue.  It should go in a separate protocol.
00367   static string event_queue_ws_type() {
00368     return WSPR_WS_TYPE("event");
00369   }
00370 
00371   static string event_queue_ws_group() {
00372     return WSPR_WS_TYPE("event");
00373   }
00374 
00375   // This is for the EventQueue.  It should go in a separate protocol.
00376   struct MessageDeliverEvent :
00377     public protocol::MessageWebService<DeliverEvent>
00378   {
00379     typedef std::vector<uid_type> key_container;
00380     key_container keys;
00381     properties_ptr template_data;
00382 
00383     explicit MessageDeliverEvent(Properties * template_data = new Properties) :
00384       keys(), template_data(template_data)
00385     { }
00386 
00387     explicit MessageDeliverEvent(const properties_ptr & template_data) :
00388       keys(), template_data(template_data)
00389     { }
00390 
00391     template<class Archive>
00392     void serialize(Archive & ar, const unsigned int) {
00393       ar & keys & template_data;
00394     }
00395   };
00396 
00397   struct MessageDeliverEvents :
00398     public protocol::MessageWebService<DeliverEvents>
00399   {
00400     typedef std::vector<uid_type> key_container;
00401     typedef std::vector<Properties> event_container;
00402     key_container keys;
00403     event_container events;
00404 
00405     explicit MessageDeliverEvents(const unsigned int size = 1) :
00406       keys(), events(size)
00407     { }
00408 
00409     explicit MessageDeliverEvents(event_container && events) :
00410       keys(), events(events)
00411     { }
00412 
00413     template<class Archive>
00414     void serialize(Archive & ar, const unsigned int) {
00415       ar & keys & events;
00416     }
00417   };
00418 
00419   WISP_ONE_WAY_CALL(caller_type, OneWay);
00420   WISP_ONE_WAY_CALL(caller_type, Response);
00421   WISP_ONE_WAY_CALL(caller_type, DeliverEvent);
00422   WISP_ONE_WAY_CALL(caller_type, DeliverEvents);
00423 
00424   WISP_TWO_WAY_CALL(caller_type, TwoWay, Response);
00425 };
00426 
00427 struct WebServiceCallContextOneWay {
00428   session_ptr session;
00429 
00430   WebServiceCallContextOneWay(const session_ptr & session) :
00431     session(session)
00432   { }
00433 };
00434 
00435 struct WebServiceCallContextTwoWay : public WebServiceCallContextOneWay {
00436   wisp_call_token token;
00437   string sender;
00438 
00439   WebServiceCallContextTwoWay(const session_ptr & session,
00440                               const wisp_call_token token,
00441                               const string & sender) :
00442     WebServiceCallContextOneWay(session), token(token), sender(sender)
00443   { }
00444 };
00445 
00446 __END_NS_SSRC_WSPR_WS
00447 
00448 #endif

Savarese Software Research Corporation
Copyright © 2006-2011 Savarese Software Research Corporation. All rights reserved.