Remove dynamic exceptions
[anna.git] / include / anna / ldap / Engine.hpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #ifndef anna_ldap_Engine_hpp
10 #define anna_ldap_Engine_hpp
11
12 #include <map>
13 #include <string>
14
15 #include <anna/app/Component.hpp>
16
17 namespace anna {
18
19 namespace ldap {
20
21 class Session;
22
23 /**
24    Gestor general de conexiones realizadas a diversos servidores LDAP.
25
26    Optimiza la creacion, busqueda y liberacion de las sesiónes establecidas contra un
27    numero indeterminado de servidores LDAP.
28
29    El siguiente codigo muestra un ejemplo de implementacion:
30
31    \code
32
33       class MyEngine : public ldap::Engine {
34       public:
35          MyEngine () {;}
36
37       private:
38          anna::Recycler<MySession> a_sessions;
39
40          anna::ldap::Session* allocateSession (const int category) { return a_sessions.create (); }
41
42          void releaseSession (anna::ldap::Session* session) {
43             MySession* aux = static_cast <MySession*> (session);
44             a_sessions.release (aux);
45          }
46       };
47
48    \endcode
49 */
50 class Engine : public app::Component {
51 public:
52   /**
53    * Máscara de los niveles de depuración que pueden ser usados en el método #setDebugLevel
54    * \see Engine
55    */
56   struct DebugLevel { enum _v { All = -1, None = 0 }; };
57
58   /**
59    * Devuelve el valor del indicador de conexión automática. Por defecto este indicador será \em true.
60    * \return el valor del indicador de conexión automática.
61    */
62   bool getAutoBind() const { return a_autoBind; }
63
64   /**
65    * Establece el indicador de conexión automática. En caso de no indicarse será \em true.
66    * \param autoBind Valor que tomará el indicador de conexión automática.
67    *
68    * Si es necesario cambiar el temporizador del Bind de una sesión LDAP, primero habrá que
69    * crearla sin conexión automática, cambiar el temporizador asociado e invocar al Bind invocando
70    * implícitamente al método ldap::Session::bind.
71    */
72   void setAutoBind(const bool autoBind) { a_autoBind = autoBind; }
73
74   /**
75      Crea o reusa una sesión LDAP con los parámetros recibidos.
76
77      Las sesiónes LDAP estaran definidas univocamente por la pareja (url, user) si al
78      invocar a este metodo ya existiera una sesión identificada por los mismos parámetros
79      recibidos, se devolvera su instancia.
80
81      Si no existe una sesión identificada por la pareja (url, user) se creara mediate la llamada
82      al metodo virtual puro (#allocateSession), se realizara la peticion de conexion y se devolvera
83      esta nueva instancia.
84
85      Dependiendo del indicador de conexión automática se solicitará la conexión al servidor
86      o será el programador quien tenga que invocarlo mediate la llamada al método ldap::Session::bind.
87
88      \param url Direccion donde atiende peticiones el servidor LDAP.
89      \param user Usuario requerido para establecer la conexion contra el servidor LDAP.
90      \param password Password requerido para establecer la conexion contra el servidor LDAP.
91      \param category Identifica el tipo de sesión a crear.
92
93      \return La session identificada por la \em url y \em user indicados como parametro.
94
95      \warning La conexion no estara totalmente operativa hasta que no se reciba la notificacion
96      correspondiente en el metodo Session::eventResponse confirmando que el ClassCode::Bind se ha
97      realizado correctamente.
98   */
99   Session* createSession(const char* url, const char* user, const char* password, const int category = 0)
100   noexcept(false);
101
102   /**
103      Crea o reusa una sesión LDAP con los parámetros recibidos.
104
105      Las sesiónes LDAP estaran definidas univocamente por la pareja (url, id) si al
106      invocar a este metodo ya existiera una sesión identificada por los mismos parámetros
107      recibidos, se devolvera su instancia.
108
109      Si no existe una sesión identificada por la pareja (url, id) se creara mediate la llamada
110      al metodo virtual puro (#allocateSession), se realizara la peticion de conexion y se devolvera
111      esta nueva instancia.
112
113      Dependiendo del indicador de conexión automática se solicitará la conexión al servidor
114      o será el programador quien tenga que invocarlo mediate la llamada al método ldap::Session::bind.
115
116      \param url Direccion donde atiende peticiones el servidor LDAP.
117      \param id Identificador usado para identificar la sesión.
118      \param user Usuario requerido para establecer la conexion contra el servidor LDAP.
119      \param password Password requerido para establecer la conexion contra el servidor LDAP.
120      \param category Identifica el tipo de sesión a crear.
121
122      \return La session identificada por la \em url y \em id indicados como parametro.
123
124      \warning La conexion no estara totalmente operativa hasta que no se reciba la notificacion
125      correspondiente en el metodo Session::eventResponse confirmando que el ClassCode::Bind se ha
126      realizado correctamente.
127   */
128   Session* createSession(const char* url, const int id, const char* user, const char* password, const int category = 0)
129   noexcept(false);
130
131   /**
132      Crea o reusa una sesión LDAP con los parámetros recibidos a un servidor que no requiera identificar
133      el usuario que solicita la conexion.
134
135      Las sesiónes LDAP estaran definidas univocamente por la pareja (url, user="") si al
136      invocar a este metodo ya existiera una sesión identificada por los mismos parámetros
137      recibidos, se devolvera su instancia.
138
139      Si no existe una sesión identificada por la pareja (url, user="") se creara mediate la llamada
140      al metodo virtual puro (#allocateSession), se realizara la peticion de conexion y se devolvera
141      esta nueva instancia.
142
143      \param url Direccion donde atiende peticiones el servidor LDAP.
144      \param category Identifica el tipo de sesión a crear.
145
146      \return La session identificada por la \em url indicada como parametro.
147
148      \warning La conexion no estara totalmente operativa hasta que no se reciba la notificacion
149      correspondiente en el metodo Session::eventResponse confirmando que el ClassCode::Bind se ha
150      realizado correctamente.
151   */
152   Session* createSession(const char* url, const int category = 0) noexcept(false) {
153     return createSession(url, NULL, NULL, category);
154   }
155
156   /**
157      Devuelve la instancia de la sesión identificada por la pareja (url, user) recibidos como parámetros.
158
159      \param url Direccion de la maquina donde atiendo peticiones el servidor LDAP.
160      \param user Usuario requerido para establecer la conexion contra el servidor LDAP.
161      \param emode Modo de actuar en caso de que no exista una sesión que coincida con los parámetros indicados.
162
163      \return La instancia de la sesión identificada por la pareja (url, user) recibidos como parámetros.
164
165      \warning Si no hay ninguna sesión identificada por la pareja (url, user) se devolvera una excepción.
166   */
167   Session* findSession(const char* url, const char* user, Exception::Mode::_v emode = Exception::Mode::Throw) noexcept(false);
168
169   /**
170      Devuelve la instancia de la sesión identificada por la pareja (url, id) recibidos como parámetros.
171
172      \param url Direccion de la maquina donde atiendo peticiones el servidor LDAP.
173      \param id Identificador indicado para establecer la conexion contra el servidor LDAP.
174      \param emode Modo de actuar en caso de que no exista una sesión que coincida con los parámetros indicados.
175
176      \return La instancia de la sesión identificada por la pareja (url, id) recibidos como parámetros.
177
178      \warning Si no hay ninguna sesión identificada por la pareja (url, id) se devolvera una excepción.
179   */
180   Session* findSession(const char* url, const int id, Exception::Mode::_v emode = Exception::Mode::Throw) noexcept(false);
181
182   /**
183      Devuelve la instancia de la sesión identificada por la pareja (url, user="") recibidos como parámetros.
184
185      \param url Direccion de la maquina donde atiendo peticiones el servidor LDAP.
186      \param emode Modo de actuar en caso de que no exista una sesión que coincida con los parámetros indicados.
187
188      \return La instancia de la sesión identificada por la pareja (url, user="") recibidos como parámetros.
189
190      \warning Si no hay ninguna sesión identificada por la pareja (url, user) se devolvera una excepción.
191   */
192   Session* findSession(const char* url, Exception::Mode::_v emode = Exception::Mode::Throw) noexcept(false) {
193     return findSession(url, (const char*) NULL, emode);
194   }
195
196   /**
197    * Libera todos los recursos asociados a una sesión LDAP, creada previemante con createSession. Si la sesión
198    * fuera NULL esta operación no tendrá ningún efecto.
199    * \param session Session LDAP a liberar.
200    */
201   void closeSession(Session* session) noexcept(false);
202
203   /**
204      Devuelve un documento XML con la informacion relevante sobre esta instancia.
205      \param parent Nodo XML del que colgar la informacion referente a esta instancia.
206      \return Un documento XML con la informacion relevante sobre esta instancia.
207   */
208   virtual xml::Node* asXML(xml::Node* parent) const ;
209
210   /**
211      Devuelve el nombre lógico de este anna::app::Component.
212      \return El nombre lógico de este anna::app::Component.
213   */
214   static const char* getClassName() { return "anna::ldap::Engine"; }
215
216   /**
217    * Establece el nivel de depuración de las operaciones del OpenLDAP.
218    * \param level Máscara que indica los elementos a depurar. Básicamente 0 para desactivar las trazas de depuración y -1 para
219    * activar el trazado de todo.
220    * \return El nivel de depuración anterior.
221    * \see http://www.openldap.org/doc/admin23/runningslapd.html para más niveles.
222    * \see DebugLevel
223    */
224   static int setDebugLevel(const int level) noexcept(false);
225
226 protected:
227   /**
228      Constructor.
229   */
230   Engine();
231
232   /**
233      Metodo invocado para instanciar sesiónes.
234
235      Para la creacion y liberacion de sesiónes es muy aconsejable usar el patron anna::Recycler.
236
237      \param category Identifica la categoria o clase de sesión que deseamos instanciar. Este paremetro
238      es el mismo indicado en el #createSession. Facilita que una misma aplicacion pueda crear un numero
239      indeterminado de sesiónes de distintos tipos, es decir, que actuen de forma distinta a la hora
240      de recoger los resultados de las peticiones.
241
242      \see anna::Recycler
243   */
244   virtual Session* allocateSession(const int category)  = 0;
245
246   /**
247      Metodo invocado para liberar sesiónes. En caso de que nuestra aplicacion requiera varios tipos de
248      sesiónes LDAP habra que tener en cuenta el valor devuelto por ldap::Session::getCategory y liberar
249      el tipo adecuado de sesión.
250      \see anna::Recycler
251   */
252   virtual void releaseSession(Session*)  = 0;
253
254 private:
255   typedef std::pair <std::string, std::string> session_key;
256   typedef std::map <session_key, Session*> session_container;
257   typedef session_container::value_type session_value_type;
258   typedef session_container::iterator session_iterator;
259   typedef session_container::const_iterator const_session_iterator;
260
261   session_container a_sessions;
262   std::string a_auxURL; // Usada para contenar el ldap:// si fuera necesario
263   bool a_autoBind;
264
265   void do_initialize() {;}
266   void do_stop() ;
267
268   const char* completeURL(const char* url) ;
269
270   session_iterator session_find(const char* url, const char* user) {
271     return a_sessions.find(session_key(url, user));
272   }
273   session_iterator session_find(const std::string& url, const std::string& user) {
274     return a_sessions.find(session_key(url, user));
275   }
276   session_iterator session_find(const char* url, const int id) ;
277
278   session_iterator session_begin() { return a_sessions.begin(); }
279   session_iterator session_end() { return a_sessions.end(); }
280   static Session* session(session_iterator ii) { return ii->second; }
281
282   const_session_iterator session_begin() const { return a_sessions.begin(); }
283   const_session_iterator session_end() const { return a_sessions.end(); }
284   static const Session* session(const_session_iterator ii) { return ii->second; }
285
286   // Para el truco de poner a la alarma antes de invocar al ldap_result
287   static void alarmnCatcher(int) ;
288
289 };
290
291 }
292 }
293
294 #endif
295