1 /***************************************************************************
2            ulxr-method_adder.h  -  interface for adding methods
3                              -------------------
4     begin                : Thu Jul 12 2007
5     copyright            : (C) 2002-2007 by Ewald Arnold
6     email                : ulxmlrpcpp@ewald-arnold.de
7 
8     $Id: ulxr_method_adder.h 1164 2010-01-06 10:03:51Z ewald-arnold $
9 
10  ***************************************************************************/
11 
12 /**************************************************************************
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU Lesser General Public License as
16  * published by the Free Software Foundation; either version 2 of the License,
17  * or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27  *
28  ***************************************************************************/
29 
30 #ifndef ULXR_METHOD_ADDER_H
31 #define ULXR_METHOD_ADDER_H
32 
33 #include <ulxmlrpcpp/ulxmlrpcpp.h>  // always first header
34 
35 namespace ulxr {
36 
37 
38 class MethodResponse;
39 class MethodCall;
40 class Dispatcher;
41 class Signature;
42 
43 
44 namespace hidden {
45 
46 
47 /** Internal helper class, not intended for public use.
48  */
49 class ULXR_API_DECL0 MethodWrapperBase
50 {
51   public:
52 
53     virtual ~MethodWrapperBase();
54 
55     virtual MethodResponse call(const MethodCall &calldata) const = 0;
56 };
57 
58 
59 /** Internal helper class template, not intended for public use.
60  */
61 template <class T>
62 class MethodWrapper : public MethodWrapperBase
63 {
64   public:
65 
66    typedef MethodResponse (T::*PMF)(const MethodCall &calldata);
67 
~MethodWrapper()68    virtual ~MethodWrapper()
69    {
70    }
71 
call(const MethodCall & calldata)72    virtual MethodResponse call (const MethodCall &calldata) const
73    {
74       return (obj->*adr) (calldata);
75    }
76 
MethodWrapper(T * o,PMF a)77    MethodWrapper(T *o, PMF a)
78     : obj(o), adr(a)
79      {}
80 
81   private:
82    T    *obj;
83    PMF   adr ;
84 
85  private:
86     // forbid them all due to internal pointers
87     const MethodWrapper& operator= (const MethodWrapper&);
88     MethodWrapper (const MethodWrapper&);
89 };
90 
91 
92 }  // namespace hidden
93 
94 
95 /** Define interface for adding rpc method to a dispatcher
96   * @ingroup grp_ulxr_rpc
97   */
98 class ULXR_API_DECL0 MethodAdder
99 {
100   public:
101 
102     typedef MethodResponse (*StaticMethodCall_t)(const MethodCall &);
103 
104     typedef MethodResponse (*SystemMethodCall_t)(const MethodCall &,
105                                                  const Dispatcher* disp);
106 
107     typedef hidden::MethodWrapperBase*  DynamicMethodCall_t;    // call Wrappers call();
108 
109     enum   CallType { CallNone,
110                       CallSystem,
111                       CallStatic,
112                       CallDynamic
113                     };
114 
115   protected:
116 
117     friend StaticMethodCall_t make_method(const StaticMethodCall_t);
118 
119     typedef union
120     {
121        StaticMethodCall_t    static_function;
122        SystemMethodCall_t    system_function;
123        DynamicMethodCall_t   dynamic_function;
124     } MethodCall_t;
125 
126   public:
127 
~MethodAdder()128     virtual ~MethodAdder()
129     {}
130 
131  /** Adds a user defined (static) method to the dispatcher.
132    * You access a remote method by sending the "official" name. Sometimes
133    * a method accepts different parameter sets (overloading in C++).
134    * In this case you add the according signature. Finally you can
135    * add a description to show the usage of this method.
136    * @param  adr            the pointer to the implementation of the method
137    * @param  ret_signature  the signature of the return value
138    * @param  name           the name of the method
139    * @param  signature      the signature of the parameters
140    * @param  help           short usage description
141    */
142    virtual void addMethod (StaticMethodCall_t adr,
143                    const CppString &ret_signature,
144                    const CppString &name,
145                    const CppString &signature,
146                    const CppString &help) = 0;
147 
148  /** Adds a user defined (dynamic) method to the dispatcher.
149    * You access a remote method by sending the "official" name. Sometimes
150    * a method accepts different parameter sets (overloading in C++).
151    * In this case you add the according signature. Finally you can
152    * add a description to show the usage of this method.
153    * @param  wrapper        the pointer to the wrapper to the method.
154    *                        Important: Dispatcher owns now and deletes this wrapper object!
155    * @param  ret_signature  the signature of the return value
156    * @param  name           the name of the method
157    * @param  signature      the signature of the parameters
158    * @param  help           short usage description
159    */
160    virtual void addMethod (DynamicMethodCall_t wrapper,
161                    const CppString &ret_signature,
162                    const CppString &name,
163                    const CppString &signature,
164                    const CppString &help) = 0;
165 
166  /** Adds a system internal method to the dispatcher.
167    * You access a remote method by sending the "official" name. Sometimes
168    * a method accepts different parameter sets (overloading in C++).
169    * In this case you add the according signature. Finally you can
170    * add a description to show the usage of this method.
171    * @param  adr            the pointer to the implementation of the method
172    * @param  ret_signature  the signature of the return value
173    * @param  name           the name of the method
174    * @param  signature      the signature of the parameters
175    * @param  help           short usage description
176    */
177    virtual void addMethod (SystemMethodCall_t adr,
178                    const CppString &ret_signature,
179                    const CppString &name,
180                    const CppString &signature,
181                    const CppString &help) = 0;
182 
183  /** Adds a user defined (static) method to the dispatcher.
184    * You access a remote method by sending the "official" name. Sometimes
185    * a method accepts different parameter sets (overloading in C++).
186    * In this case you add the according signature. Finally you can
187    * add a description to show the usage of this method.
188    * @param  adr            the pointer to the implementation of the method
189    * @param  ret_signature  the signature of the return value
190    * @param  name           the name of the method
191    * @param  signature      the signature of the parameters
192    * @param  help           short usage description
193    */
194    virtual void addMethod (StaticMethodCall_t adr,
195                    const Signature &ret_signature,
196                    const CppString &name,
197                    const Signature &signature,
198                    const CppString &help) = 0;
199 
200  /** Adds a user defined (dynamic) method to the dispatcher.
201    * You access a remote method by sending the "official" name. Sometimes
202    * a method accepts different parameter sets (overloading in C++).
203    * In this case you add the according signature. Finally you can
204    * add a description to show the usage of this method.
205    * @param  wrapper        the pointer to the wrapper to the method.
206    *                        Important: Dispatcher owns now and deletes this wrapper object!
207    * @param  ret_signature  the signature of the return value
208    * @param  name           the name of the method
209    * @param  signature      the signature of the parameters
210    * @param  help           short usage description
211    */
212    virtual void addMethod (DynamicMethodCall_t wrapper,
213                    const Signature &ret_signature,
214                    const CppString &name,
215                    const Signature &signature,
216                    const CppString &help) = 0;
217 
218  /** Adds a system internal method to the dispatcher.
219    * You access a remote method by sending the "official" name. Sometimes
220    * a method accepts different parameter sets (overloading in C++).
221    * In this case you add the according signature. Finally you can
222    * add a description to show the usage of this method.
223    * @param  adr            the pointer to the implementation of the method
224    * @param  ret_signature  the signature of the return value
225    * @param  name           the name of the method
226    * @param  signature      the signature of the parameters
227    * @param  help           short usage description
228    */
229    virtual void addMethod (SystemMethodCall_t adr,
230                    const Signature &ret_signature,
231                    const CppString &name,
232                    const Signature &signature,
233                    const CppString &help) = 0;
234 
235  /** Removes a method if available
236    * @param name   method name
237    */
238    virtual void removeMethod(const CppString &name) = 0;
239 };
240 
241 
242 /** Creates a wrapper object to a method of a worker class.
243   * new ulxr::hidden::MethodWrapper<classname> (&obj, &classname::method),
244   * @param w     reference to worker class
245   * @param pmf   adress of member function in worker class
246   * @return pointer to wrapper object
247   */
248 
249 #ifndef _MSC_VER
250 
251 template <class T>
252 inline hidden::MethodWrapperBase*
make_method(T & w,typename hidden::MethodWrapper<T>::PMF pmf)253 make_method(T &w, typename hidden::MethodWrapper<T>::PMF pmf)
254 {
255   return new hidden::MethodWrapper<T> (&w, pmf);
256 }
257 
258 #else // work around m$vc bug
259 
260 template <class T, class U>
261 inline hidden::MethodWrapper<T>*
make_method(T & w,U pmf)262 make_method(T &w, U pmf)
263 {
264   return new hidden::MethodWrapper<T> (&w, pmf);
265 }
266 
267 #endif
268 
269 typedef MethodAdder::StaticMethodCall_t MethodAdder_StaticMethodCall_t;
270 
271 /** Specialisation of template to achive uniform look in responder creation.
272   * @param ptr   pointer to worker function
273   * @return pointer to the function
274   */
275 inline MethodAdder_StaticMethodCall_t
make_method(MethodAdder_StaticMethodCall_t ptr)276 make_method(MethodAdder_StaticMethodCall_t ptr)
277 {
278   return ptr;
279 }
280 
281 
282 } // namespace
283 
284 #endif // ULXR_METHOD_ADDER_H
285