View Javadoc

1   /**
2    * LICENCIA LGPL:
3    * 
4    * Esta librería es Software Libre; Usted puede redistribuirla y/o modificarla
5    * bajo los términos de la GNU Lesser General Public License (LGPL) tal y como 
6    * ha sido publicada por la Free Software Foundation; o bien la versión 2.1 de 
7    * la Licencia, o (a su elección) cualquier versión posterior.
8    * 
9    * Esta librería se distribuye con la esperanza de que sea útil, pero SIN 
10   * NINGUNA GARANTÍA; tampoco las implícitas garantías de MERCANTILIDAD o 
11   * ADECUACIÓN A UN PROPÓSITO PARTICULAR. Consulte la GNU Lesser General Public 
12   * License (LGPL) para más detalles
13   * 
14   * Usted debe recibir una copia de la GNU Lesser General Public License (LGPL) 
15   * junto con esta librería; si no es así, escriba a la Free Software Foundation 
16   * Inc. 51 Franklin Street, 5º Piso, Boston, MA 02110-1301, USA o consulte
17   * <http://www.gnu.org/licenses/>.
18   *
19   * Copyright 2011 Agencia de Tecnología y Certificación Electrónica
20   */
21  package es.accv.arangi.base.ldap;
22  
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.Iterator;
26  import java.util.List;
27  
28  import org.apache.log4j.Logger;
29  
30  import com.novell.ldap.LDAPAttribute;
31  import com.novell.ldap.LDAPConnection;
32  import com.novell.ldap.LDAPEntry;
33  import com.novell.ldap.LDAPModification;
34  import com.novell.ldap.LDAPSearchResults;
35  
36  import es.accv.arangi.base.exception.ldap.LDAPException;
37  
38  /**
39   * Esta clase ofrece métodos de alto nivel para buscar DNs dentro de un
40   * directorio LDAP, así como para copiar o mover elementos entre sus ramas.<br><br>
41   * 
42   * Requiere de servidores que cumplan la versión 3 de LDAP.
43   * 
44   * @author <a href="mailto:jgutierrez@accv.es">José M Gutiérrez</a>
45   */
46  public class LDAP {
47  
48  	/**
49  	 * Puerto por defecto para LDAP (389)
50  	 */
51  	public static final int LDAP_DEFAULT_PORT = 389;
52  	
53  	
54  	/**
55  	 * Logger de la clase
56  	 */
57  	Logger logger = Logger.getLogger(LDAP.class);
58  	
59  	/**
60  	 * Conexión LDAP
61  	 */
62  	LDAPConnection lc;
63  	
64  	/**
65  	 * Constructor
66  	 * 
67  	 * @param host Host LDAP
68  	 * @param port Puerto del LDAP (normalmente 389)
69  	 * @param user Usuario LDAP
70  	 * @param password Contraseña para el usuario LDAP
71  	 * @throws LDAPException Excepción accediendo al LDAP
72  	 */
73  	public LDAP (String host, int port, String user, String password) throws LDAPException {
74  
75  		logger.debug("[LDAP]::Entrada:: " + Arrays.asList(new Object[] { host, port, user }));
76  		
77  		lc = new LDAPConnection();
78  		try {
79  			lc.connect(host, port);
80  		} catch (com.novell.ldap.LDAPException e) {
81  			logger.info ("[LDAP]::No ha sido posible conectarse al host " + host + ":" + port, e);
82  			throw new LDAPException ("No ha sido posible conectarse al host " + host + ":" + port, e);
83  		}
84  		try {
85  			lc.bind( LDAPConnection.LDAP_V3, user, password.getBytes() );
86  		} catch (com.novell.ldap.LDAPException e) {
87  			logger.info ("[LDAP]::No ha sido posible autenticarse en el host " + host + ":" + port, e);
88  			throw new LDAPException ("No ha sido posible autenticarse en el al host " + host + ":" + port, e);
89  		}
90  
91  	}
92  	
93  	/**
94  	 * Constructor
95  	 * 
96  	 * @param host Host LDAP
97  	 * @param user Usuario LDAP
98  	 * @param password Contraseña para el usuario LDAP
99  	 * @throws LDAPException Excepción accediendo al LDAP
100 	 */
101 	public LDAP (String host, String user, String password) throws LDAPException {
102 		this(host, LDAP_DEFAULT_PORT, user, password);
103 	}
104 	
105 	/**
106 	 * Realiza una búsqueda de DNs en una rama en base a un filtro
107 	 * 
108 	 * @param branch Rama sobre la que realizar la búsqueda
109 	 * @param filter Filtro
110 	 * @return Lista de DNs de la rama que coinciden con el filtro
111 	 * @throws LDAPException 
112 	 */
113 	public List<String> getDNs (String branch, String filter) throws LDAPException {
114 		
115 		logger.debug("[LDAP.getDNs]::Entrada::" + Arrays.asList(new Object[] { branch, filter }));
116 				
117 		LDAPSearchResults results;
118 		try {
119 			results = lc.search(branch, LDAPConnection.SCOPE_ONE, filter, null, false);
120 		} catch (com.novell.ldap.LDAPException e) {
121 			logger.info ("[LDAP.getDNs]::Ha ocurrido un error realizando la búsqueda", e);
122 			throw new LDAPException ("Ha ocurrido un error realizando la búsqueda", e);
123 		}
124 		List<String> result = new ArrayList<String>();
125 		while (results.hasMore()) {
126 			LDAPEntry entry;
127 			try {
128 				entry = results.next();
129 			} catch (com.novell.ldap.LDAPException e) {
130 				logger.info ("[LDAP.getDNs]::Ha ocurrido un error recuperando una de las entradas resultado de la búsqueda", e);
131 				throw new LDAPException ("Ha ocurrido un error recuperando una de las entradas resultado de la búsqueda", e);
132 			}
133 			result.add(entry.getDN());
134 		}
135 		
136 		logger.debug("[LDAP.getDNs]::Se devolverán " + result.size() + " elementos.");
137 		
138 		return result;
139 	}
140 	
141 	/**
142 	 * Copia una entrada a un dn destino. Si el DN destino no
143 	 * existe lo crea. Si ya existía añade el elemento.
144 	 * 
145 	 * @param dnOrigin DN origen
146 	 * @param dnDestination DN destino
147 	 * @throws Exception 
148 	 */
149 	public void copy (String dnOrigin, String dnDestination) throws LDAPException {
150 		
151 		logger.debug("[LDAP.copy]::Entrada::" + Arrays.asList(new Object[] { dnOrigin, dnDestination }));
152 
153 		//-- Buscar origen
154 		LDAPEntry entryOrigen;
155 		try {
156 			entryOrigen = getEntry(dnOrigin);
157 		} catch (com.novell.ldap.LDAPException e1) {
158 			logger.info("[LDAP.copy]::Se ha producido un error buscando la entrada origen: " + dnOrigin);
159 			throw new LDAPException ("Se ha producido un error buscando la entrada origen: " + dnOrigin);
160 		}
161 		if (entryOrigen == null) {
162 			logger.info("[LDAP.copy]::No se ha encontrado la entrada origen: " + dnOrigin);
163 			throw new LDAPException ("No se ha encontrado la entrada para el DN '" + dnOrigin + "'");
164 		}
165 		logger.debug("[LDAP.copy]::Encontrada entrada origen: " + dnOrigin);
166 
167 		//-- Buscar destino
168 		LDAPEntry entryDestino;
169 		try {
170 			entryDestino = getEntry (dnDestination);
171 		} catch (com.novell.ldap.LDAPException e1) {
172 			logger.info("[LDAP.copy]::Se ha producido un error buscando la entrada destino: " + dnDestination);
173 			throw new LDAPException ("Se ha producido un error buscando la entrada destino: " + dnDestination);
174 		}
175 		if (entryDestino != null) {
176 			logger.debug("[LDAP.copy]::Encontrada entrada destino: " + dnDestination);
177 
178 			//-- Modificar el destino para añadirle todos los atributos binarios del origen
179 			List<LDAPModification> lModificaciones = new ArrayList<LDAPModification>();
180 			for (Iterator iterator = entryOrigen.getAttributeSet().iterator(); iterator.hasNext();) {
181 				
182 				LDAPAttribute attrOrigen = (LDAPAttribute)iterator.next();
183 				
184 				if (attrOrigen.hasSubtype("binary")) {
185 					
186 					//-- Crear la modificación
187 					logger.debug("[LDAP.copy]::Añadir atributo '" + attrOrigen.getBaseName() + "' al destino: " + dnDestination);
188 					LDAPModification modification = new LDAPModification(LDAPModification.ADD, attrOrigen);
189 					
190 					lModificaciones.add (modification);
191 				}
192 			}
193 			
194 			//-- Realizar las modificaciones
195 			try {
196 				lc.modify(dnDestination, lModificaciones.toArray(new LDAPModification[0]));
197 			} catch (com.novell.ldap.LDAPException e) {
198 				logger.info ("[LDAP.getDNs]::No se ha podido modificar la entrada con DN=" + dnDestination, e);
199 				throw new LDAPException ("No se ha podido modificar la entrada con DN=" + dnDestination, e);
200 			}
201 			
202 		} else {
203 			//-- Crear en destino una copia del origen
204 			logger.debug("[LDAP.copy]::No se ha encontrado la entrada destino: " + dnDestination);
205 			entryDestino = new LDAPEntry(dnDestination, entryOrigen.getAttributeSet());
206 			try {
207 				lc.add (entryDestino);
208 			} catch (com.novell.ldap.LDAPException e) {
209 				logger.info ("[LDAP.getDNs]::No se ha podido añadir la entrada con DN=" + dnDestination, e);
210 				throw new LDAPException ("No se ha podido añadir la entrada con DN=" + dnDestination, e);
211 			}
212 		}
213 	}
214 	
215 	/**
216 	 * Mueve una entrada a un dn destino. Si el DN destino no
217 	 * existe lo crea. Si ya existía añade el elemento.
218 	 * 
219 	 * @param dnOrigin DN origen
220 	 * @param dnDestination DN destino
221 	 * @throws LDAPException 
222 	 */
223 	public void move (String dnOrigin, String dnDestination) throws LDAPException {
224 		
225 		logger.debug("[LDAP.move]::Entrada::" + Arrays.asList(new Object[] { dnOrigin, dnDestination }));
226 
227 		//-- Copiar 
228 		copy (dnOrigin, dnDestination);
229 		logger.debug("[LDAP.move]::Se ha realizado la copia::" + Arrays.asList(new Object[] { dnOrigin, dnDestination }));
230 		
231 		//-- Todo ha ido bien, eliminar el origen
232 		try {
233 			lc.delete(dnOrigin);
234 		} catch (com.novell.ldap.LDAPException e) {
235 			logger.info ("[LDAP.getDNs]::No se ha podido eliminar la entrada con DN=" + dnOrigin, e);
236 			throw new LDAPException ("No se ha podido eliminar la entrada con DN=" + dnOrigin, e);
237 		}
238 		logger.debug("[LDAP.move]::Se ha eliminado la entrada: " + dnOrigin);
239 	}
240 	
241 	/**
242 	 * Cierra la conexión
243 	 * 
244 	 * @throws LDAPException 
245 	 */
246 	public void close () throws LDAPException {
247 		
248 		logger.debug("[LDAP.close]::Entrada");
249 
250 		try {
251 			lc.disconnect();
252 		} catch (com.novell.ldap.LDAPException e) {
253 			logger.info ("[LDAP.getDNs]::No se ha podido cerrar la conexión con el servidor LDAP", e);
254 			throw new LDAPException ("No se ha podido cerrar la conexión con el servidor LDAP", e);
255 		}
256 		logger.debug("[LDAP.close]::Se ha cerrado la conexión con el servidor LDAP");
257 	}
258 	
259 	
260 	/*
261 	 * Obtiene una entrada en base a su DN
262 	 */
263 	private LDAPEntry getEntry (String dn) throws com.novell.ldap.LDAPException {
264 		LDAPSearchResults results = lc.search(dn, LDAPConnection.SCOPE_BASE, null, null, false);
265 		Object object;
266 		try {
267 			object = results.next();
268 		} catch (com.novell.ldap.LDAPException e) {
269 			return null;
270 		}
271 		if (!(object instanceof LDAPEntry)) {
272 			return null;
273 		}
274 		
275 		return (LDAPEntry) object;
276 	}
277 	
278 	
279 //	public static void main (String[] args) {
280 //		
281 //		String host = "192.168.161.2";
282 //		int port = 389;
283 //		String user = "cn=Admin,o=Generalitat Valenciana,c=ES";
284 //		String password = "baltimore";
285 //		
286 //		LDAP ldap = null;
287 //		try {
288 //			ldap = new LDAP(host, port, user, password);
289 //			System.out.println ("Conectado a LDAP");
290 //			List<String> lDNs = ldap.getDNs("ou=ciudadanos,o=Generalitat Valenciana,c=es", "cn=*NIF:73387270C*");
291 //			for (Iterator iterator = lDNs.iterator(); iterator.hasNext();) {
292 //				String dn = (String) iterator.next();
293 //				String dnDest = dn.replaceFirst("ciudadanos","infonova");
294 //				System.out.println ("DN: " + dn);
295 //				ldap.copy(dn, dnDest);
296 //			}
297 //			
298 //		} catch (Exception e) {
299 //			e.printStackTrace();
300 //		} finally {
301 //			try {
302 //				ldap.close();
303 //			} catch (LDAPException e) {
304 //				e.printStackTrace();
305 //			}
306 //		}
307 //	}
308 	
309 }