1 // ANNA - Anna is Not 'N' Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // https://bitbucket.org/testillano/anna
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
37 #ifndef anna_ldap_Engine_hpp
38 #define anna_ldap_Engine_hpp
43 #include <anna/app/Component.hpp>
52 Gestor general de conexiones realizadas a diversos servidores LDAP.
54 Optimiza la creacion, busqueda y liberacion de las sesiónes establecidas contra un
55 numero indeterminado de servidores LDAP.
57 El siguiente codigo muestra un ejemplo de implementacion:
61 class MyEngine : public ldap::Engine {
66 anna::Recycler<MySession> a_sessions;
68 anna::ldap::Session* allocateSession (const int category) throw () { return a_sessions.create (); }
70 void releaseSession (anna::ldap::Session* session) throw () {
71 MySession* aux = static_cast <MySession*> (session);
72 a_sessions.release (aux);
78 class Engine : public app::Component {
81 * Máscara de los niveles de depuración que pueden ser usados en el método #setDebugLevel
84 struct DebugLevel { enum _v { All = -1, None = 0 }; };
87 * Devuelve el valor del indicador de conexión automática. Por defecto este indicador será \em true.
88 * \return el valor del indicador de conexión automática.
90 bool getAutoBind() const throw() { return a_autoBind; }
93 * Establece el indicador de conexión automática. En caso de no indicarse será \em true.
94 * \param autoBind Valor que tomará el indicador de conexión automática.
96 * Si es necesario cambiar el temporizador del Bind de una sesión LDAP, primero habrá que
97 * crearla sin conexión automática, cambiar el temporizador asociado e invocar al Bind invocando
98 * implícitamente al método ldap::Session::bind.
100 void setAutoBind(const bool autoBind) throw() { a_autoBind = autoBind; }
103 Crea o reusa una sesión LDAP con los parámetros recibidos.
105 Las sesiónes LDAP estaran definidas univocamente por la pareja (url, user) si al
106 invocar a este metodo ya existiera una sesión identificada por los mismos parámetros
107 recibidos, se devolvera su instancia.
109 Si no existe una sesión identificada por la pareja (url, user) se creara mediate la llamada
110 al metodo virtual puro (#allocateSession), se realizara la peticion de conexion y se devolvera
111 esta nueva instancia.
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.
116 \param url Direccion donde atiende peticiones el servidor LDAP.
117 \param user Usuario requerido para establecer la conexion contra el servidor LDAP.
118 \param password Password requerido para establecer la conexion contra el servidor LDAP.
119 \param category Identifica el tipo de sesión a crear.
121 \return La session identificada por la \em url y \em user indicados como parametro.
123 \warning La conexion no estara totalmente operativa hasta que no se reciba la notificacion
124 correspondiente en el metodo Session::eventResponse confirmando que el ClassCode::Bind se ha
125 realizado correctamente.
127 Session* createSession(const char* url, const char* user, const char* password, const int category = 0)
128 throw(RuntimeException);
131 Crea o reusa una sesión LDAP con los parámetros recibidos.
133 Las sesiónes LDAP estaran definidas univocamente por la pareja (url, id) si al
134 invocar a este metodo ya existiera una sesión identificada por los mismos parámetros
135 recibidos, se devolvera su instancia.
137 Si no existe una sesión identificada por la pareja (url, id) se creara mediate la llamada
138 al metodo virtual puro (#allocateSession), se realizara la peticion de conexion y se devolvera
139 esta nueva instancia.
141 Dependiendo del indicador de conexión automática se solicitará la conexión al servidor
142 o será el programador quien tenga que invocarlo mediate la llamada al método ldap::Session::bind.
144 \param url Direccion donde atiende peticiones el servidor LDAP.
145 \param id Identificador usado para identificar la sesión.
146 \param user Usuario requerido para establecer la conexion contra el servidor LDAP.
147 \param password Password requerido para establecer la conexion contra el servidor LDAP.
148 \param category Identifica el tipo de sesión a crear.
150 \return La session identificada por la \em url y \em id indicados como parametro.
152 \warning La conexion no estara totalmente operativa hasta que no se reciba la notificacion
153 correspondiente en el metodo Session::eventResponse confirmando que el ClassCode::Bind se ha
154 realizado correctamente.
156 Session* createSession(const char* url, const int id, const char* user, const char* password, const int category = 0)
157 throw(RuntimeException);
160 Crea o reusa una sesión LDAP con los parámetros recibidos a un servidor que no requiera identificar
161 el usuario que solicita la conexion.
163 Las sesiónes LDAP estaran definidas univocamente por la pareja (url, user="") si al
164 invocar a este metodo ya existiera una sesión identificada por los mismos parámetros
165 recibidos, se devolvera su instancia.
167 Si no existe una sesión identificada por la pareja (url, user="") se creara mediate la llamada
168 al metodo virtual puro (#allocateSession), se realizara la peticion de conexion y se devolvera
169 esta nueva instancia.
171 \param url Direccion donde atiende peticiones el servidor LDAP.
172 \param category Identifica el tipo de sesión a crear.
174 \return La session identificada por la \em url indicada como parametro.
176 \warning La conexion no estara totalmente operativa hasta que no se reciba la notificacion
177 correspondiente en el metodo Session::eventResponse confirmando que el ClassCode::Bind se ha
178 realizado correctamente.
180 Session* createSession(const char* url, const int category = 0) throw(RuntimeException) {
181 return createSession(url, NULL, NULL, category);
185 Devuelve la instancia de la sesión identificada por la pareja (url, user) recibidos como parámetros.
187 \param url Direccion de la maquina donde atiendo peticiones el servidor LDAP.
188 \param user Usuario requerido para establecer la conexion contra el servidor LDAP.
189 \param emode Modo de actuar en caso de que no exista una sesión que coincida con los parámetros indicados.
191 \return La instancia de la sesión identificada por la pareja (url, user) recibidos como parámetros.
193 \warning Si no hay ninguna sesión identificada por la pareja (url, user) se devolvera una excepción.
195 Session* findSession(const char* url, const char* user, Exception::Mode::_v emode = Exception::Mode::Throw) throw(RuntimeException);
198 Devuelve la instancia de la sesión identificada por la pareja (url, id) recibidos como parámetros.
200 \param url Direccion de la maquina donde atiendo peticiones el servidor LDAP.
201 \param id Identificador indicado para establecer la conexion contra el servidor LDAP.
202 \param emode Modo de actuar en caso de que no exista una sesión que coincida con los parámetros indicados.
204 \return La instancia de la sesión identificada por la pareja (url, id) recibidos como parámetros.
206 \warning Si no hay ninguna sesión identificada por la pareja (url, id) se devolvera una excepción.
208 Session* findSession(const char* url, const int id, Exception::Mode::_v emode = Exception::Mode::Throw) throw(RuntimeException);
211 Devuelve la instancia de la sesión identificada por la pareja (url, user="") recibidos como parámetros.
213 \param url Direccion de la maquina donde atiendo peticiones el servidor LDAP.
214 \param emode Modo de actuar en caso de que no exista una sesión que coincida con los parámetros indicados.
216 \return La instancia de la sesión identificada por la pareja (url, user="") recibidos como parámetros.
218 \warning Si no hay ninguna sesión identificada por la pareja (url, user) se devolvera una excepción.
220 Session* findSession(const char* url, Exception::Mode::_v emode = Exception::Mode::Throw) throw(RuntimeException) {
221 return findSession(url, (const char*) NULL, emode);
225 * Libera todos los recursos asociados a una sesión LDAP, creada previemante con createSession. Si la sesión
226 * fuera NULL esta operación no tendrá ningún efecto.
227 * \param session Session LDAP a liberar.
229 void closeSession(Session* session) throw(RuntimeException);
232 Devuelve un documento XML con la informacion relevante sobre esta instancia.
233 \param parent Nodo XML del que colgar la informacion referente a esta instancia.
234 \return Un documento XML con la informacion relevante sobre esta instancia.
236 virtual xml::Node* asXML(xml::Node* parent) const throw();
239 Devuelve el nombre lógico de este anna::app::Component.
240 \return El nombre lógico de este anna::app::Component.
242 static const char* getClassName() throw() { return "anna::ldap::Engine"; }
245 * Establece el nivel de depuración de las operaciones del OpenLDAP.
246 * \param level Máscara que indica los elementos a depurar. Básicamente 0 para desactivar las trazas de depuración y -1 para
247 * activar el trazado de todo.
248 * \return El nivel de depuración anterior.
249 * \see http://www.openldap.org/doc/admin23/runningslapd.html para más niveles.
252 static int setDebugLevel(const int level) throw(RuntimeException);
261 Metodo invocado para instanciar sesiónes.
263 Para la creacion y liberacion de sesiónes es muy aconsejable usar el patron anna::Recycler.
265 \param category Identifica la categoria o clase de sesión que deseamos instanciar. Este paremetro
266 es el mismo indicado en el #createSession. Facilita que una misma aplicacion pueda crear un numero
267 indeterminado de sesiónes de distintos tipos, es decir, que actuen de forma distinta a la hora
268 de recoger los resultados de las peticiones.
272 virtual Session* allocateSession(const int category) throw() = 0;
275 Metodo invocado para liberar sesiónes. En caso de que nuestra aplicacion requiera varios tipos de
276 sesiónes LDAP habra que tener en cuenta el valor devuelto por ldap::Session::getCategory y liberar
277 el tipo adecuado de sesión.
280 virtual void releaseSession(Session*) throw() = 0;
283 typedef std::pair <std::string, std::string> session_key;
284 typedef std::map <session_key, Session*> session_container;
285 typedef session_container::value_type session_value_type;
286 typedef session_container::iterator session_iterator;
287 typedef session_container::const_iterator const_session_iterator;
289 session_container a_sessions;
290 std::string a_auxURL; // Usada para contenar el ldap:// si fuera necesario
293 void do_initialize() throw() {;}
294 void do_stop() throw();
296 const char* completeURL(const char* url) throw();
298 session_iterator session_find(const char* url, const char* user) throw() {
299 return a_sessions.find(session_key(url, user));
301 session_iterator session_find(const std::string& url, const std::string& user) throw() {
302 return a_sessions.find(session_key(url, user));
304 session_iterator session_find(const char* url, const int id) throw();
306 session_iterator session_begin() throw() { return a_sessions.begin(); }
307 session_iterator session_end() throw() { return a_sessions.end(); }
308 static Session* session(session_iterator ii) throw() { return ii->second; }
310 const_session_iterator session_begin() const throw() { return a_sessions.begin(); }
311 const_session_iterator session_end() const throw() { return a_sessions.end(); }
312 static const Session* session(const_session_iterator ii) throw() { return ii->second; }
314 // Para el truco de poner a la alarma antes de invocar al ldap_result
315 static void alarmnCatcher(int) throw();