1 //  Libiqxmlrpc - an object-oriented XML-RPC solution.
2 //  Copyright (C) 2011 Anton Dedov
3 
4 #include "dispatcher_manager.h"
5 
6 #include "builtins.h"
7 
8 #include <algorithm>
9 #include <deque>
10 #include <map>
11 
12 namespace iqxmlrpc {
13 
14 //
15 // Default method dispatcher
16 //
17 
18 class Default_method_dispatcher: public Method_dispatcher_base {
19   typedef std::map<std::string, Method_factory_base*> Factory_map;
20   Factory_map fs;
21 
22 public:
23   ~Default_method_dispatcher();
24 
25   void register_method(const std::string& name, Method_factory_base*);
26 
27 private:
28   virtual Method*
29   do_create_method(const std::string&);
30 
31   virtual void
32   do_get_methods_list(Array&) const;
33 };
34 
~Default_method_dispatcher()35 Default_method_dispatcher::~Default_method_dispatcher()
36 {
37   util::delete_ptrs( fs.begin(), fs.end(),
38     util::Select2nd<Factory_map>());
39 }
40 
register_method(const std::string & name,Method_factory_base * fb)41 void Default_method_dispatcher::register_method
42   ( const std::string& name, Method_factory_base* fb )
43 {
44   fs[name] = fb;
45 }
46 
do_create_method(const std::string & name)47 Method* Default_method_dispatcher::do_create_method(const std::string& name)
48 {
49   if( fs.find(name) == fs.end() )
50     return NULL;
51 
52   return fs[name]->create();
53 }
54 
do_get_methods_list(Array & retval) const55 void Default_method_dispatcher::do_get_methods_list(Array& retval) const
56 {
57   for(Factory_map::const_iterator i = fs.begin(); i != fs.end(); ++i)
58   {
59     retval.push_back(i->first);
60   }
61 }
62 
63 //
64 // System method factory
65 //
66 
67 template <class T>
68 class System_method_factory: public Method_factory_base {
69   Method_dispatcher_manager* dmgr_;
70 
71 public:
System_method_factory(Method_dispatcher_manager * dmgr)72   System_method_factory(Method_dispatcher_manager* dmgr):
73     dmgr_(dmgr)
74   {
75   }
76 
77 private:
create()78   T* create()
79   {
80     return new T(dmgr_);
81   }
82 };
83 
84 //
85 // Method dispatcher menager
86 //
87 
88 class Method_dispatcher_manager::Impl {
89 public:
90   typedef std::deque<Method_dispatcher_base*> DispatchersSet;
91   DispatchersSet dispatchers;
92   Default_method_dispatcher* default_disp;
93 
Impl()94   Impl():
95     default_disp(new Default_method_dispatcher)
96   {
97     dispatchers.push_back(default_disp);
98   }
99 
~Impl()100   ~Impl()
101   {
102     util::delete_ptrs(dispatchers.begin(), dispatchers.end());
103   }
104 };
105 
106 
Method_dispatcher_manager()107 Method_dispatcher_manager::Method_dispatcher_manager():
108   impl_(new Impl)
109 {
110 }
111 
~Method_dispatcher_manager()112 Method_dispatcher_manager::~Method_dispatcher_manager()
113 {
114   delete impl_;
115 }
116 
register_method(const std::string & name,Method_factory_base * mfactory)117 void Method_dispatcher_manager::register_method(
118   const std::string& name, Method_factory_base* mfactory)
119 {
120   impl_->default_disp->register_method(name, mfactory);
121 }
122 
push_back(Method_dispatcher_base * mdisp)123 void Method_dispatcher_manager::push_back(Method_dispatcher_base* mdisp)
124 {
125   impl_->dispatchers.push_back(mdisp);
126 }
127 
create_method(const Method::Data & mdata)128 Method* Method_dispatcher_manager::create_method(const Method::Data& mdata)
129 {
130   typedef Impl::DispatchersSet::iterator I;
131   for (I i = impl_->dispatchers.begin(); i != impl_->dispatchers.end(); ++i)
132   {
133     Method* tmp = (*i)->create_method(mdata);
134     if (tmp)
135       return tmp;
136   }
137 
138   throw Unknown_method(mdata.method_name);
139 }
140 
get_methods_list(Array & retval) const141 void Method_dispatcher_manager::get_methods_list(Array& retval) const
142 {
143   typedef Impl::DispatchersSet::const_iterator CI;
144   for (CI i = impl_->dispatchers.begin(); i != impl_->dispatchers.end(); ++i)
145     (*i)->get_methods_list(retval);
146 }
147 
enable_introspection()148 void Method_dispatcher_manager::enable_introspection()
149 {
150   impl_->default_disp->register_method("system.listMethods",
151     new System_method_factory<builtins::List_methods>(this));
152 }
153 
154 } // namespace iqxmlrpc
155