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