001 /**
002 * ESUP-Portail Helpdesk - Copyright (c) 2004-2006 ESUP-Portail consortium
003 * For any information please refer to http://esup-helpdesk.sourceforge.net
004 */
005 package org.esupportail.portal.channels.hibernate.ldap;
006
007 import java.util.Hashtable;
008 import java.util.Iterator;
009 import java.util.List;
010 import java.util.Vector;
011
012 import javax.naming.Context;
013 import javax.naming.NamingEnumeration;
014 import javax.naming.NamingException;
015 import javax.naming.directory.Attributes;
016 import javax.naming.directory.BasicAttribute;
017 import javax.naming.directory.DirContext;
018 import javax.naming.directory.InitialDirContext;
019 import javax.naming.directory.SearchControls;
020 import javax.naming.directory.SearchResult;
021
022 import org.esupportail.portal.channels.hibernate.exceptions.CLdapSearchException;
023 import org.esupportail.portal.channels.hibernate.ldap.config.CLdapSearchConfig;
024 import org.esupportail.portal.channels.hibernate.util.ALogger;
025
026 /**
027 * A class to make LDAP search.
028 */
029 public final class SLdapSearchEngine {
030
031 //eviter de se connecter plusieurs fois a l'annuaire > attribut statique pour la connexion
032
033 /**
034 * The context used to connect to the LDAP directory.
035 */
036 private static DirContext context = null;
037 /**
038 * Constructor.
039 */
040 private SLdapSearchEngine() {
041 // no instanciation of this class
042 }
043
044 /**
045 * @param logger a logger
046 * @param key the key to search for
047 * @return a List of CLdapSearchResult.
048 * @throws CLdapSearchException
049 */
050 public static List search(
051 final ALogger logger,
052 final String key) throws CLdapSearchException {
053
054 if (logger.isDebugEnabled()) {
055 logger.debug(new StringBuffer("LDAP search for '").append(key).append("'..."));
056 }
057 List ldapSearchResults = new Vector();
058 openConnectionIfNeeded(logger);
059
060 // set search parameters
061 SearchControls sc = new SearchControls();
062 sc.setSearchScope(CLdapSearchConfig.getScope());
063 try {
064 String filter = CLdapSearchConfig.getSearchAttribute() + "=*" + key + "*";
065 NamingEnumeration enumeration = null;
066 try {
067 enumeration = context.search(CLdapSearchConfig.getBase(), filter, sc);
068 } catch (NamingException e) {
069 logger.warn("could not search the LDAP directory, one attempt more.", e);
070 openConnection(logger);
071 enumeration = context.search(CLdapSearchConfig.getBase(), filter, sc);
072 }
073 while (enumeration.hasMore()) {
074 SearchResult result = (SearchResult) enumeration.next();
075 Attributes attribs = result.getAttributes();
076 BasicAttribute uidAttrib = (BasicAttribute) attribs.get(CLdapSearchConfig.getUidAttribute());
077 CLdapSearchResult ldapSearchResult = new CLdapSearchResult((String) uidAttrib.get());
078
079 BasicAttribute searchAttrib = (BasicAttribute) attribs.get(CLdapSearchConfig.getSearchAttribute());
080 int s = searchAttrib.size();
081 for (int i = 0; i < s; i++) {
082 ldapSearchResult.addSearchAttribute((String) searchAttrib.get(i));
083 }
084
085 List displayAttributes = CLdapSearchConfig.getDisplayAttributes();
086 Iterator iter = displayAttributes.iterator();
087 while (iter.hasNext()) {
088 String attributeName = (String) iter.next();
089 BasicAttribute displayAttrib = (BasicAttribute) attribs.get(attributeName);
090 if (displayAttrib != null) {
091 int d = displayAttrib.size();
092 Vector displayAttributeValues = new Vector();
093 for (int i = 0; i < d; i++) {
094 displayAttributeValues.add(displayAttrib.get(i));
095 }
096 ldapSearchResult.addDisplayAttribute(attributeName, displayAttributeValues);
097 }
098 }
099
100 ldapSearchResults.add(ldapSearchResult);
101 }
102 } catch (NamingException e) {
103 throw new CLdapSearchException("could not search the LDAP directory", e);
104 }
105
106 if (logger.isDebugEnabled()) {
107 if (ldapSearchResults.size() == 0) {
108 logger.debug("no result found.");
109 } else {
110 logger.debug(new StringBuffer().append(ldapSearchResults.size()).append(" results found:"));
111 }
112 }
113 return ldapSearchResults;
114 }
115
116 /**
117 * Open the context (if needed).
118 * @param logger a logger
119 * @throws CLdapSearchException
120 */
121 private static synchronized void openConnection(final ALogger logger) throws CLdapSearchException {
122 if (logger.isDebugEnabled()) {
123 logger.debug(new StringBuffer("opening an LDAP connection to '")
124 .append(CLdapSearchConfig.getUrl()).append("'..."));
125 }
126 Hashtable env = new Hashtable();
127 env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
128 env.put(Context.PROVIDER_URL, CLdapSearchConfig.getUrl());
129
130 String bindDn = CLdapSearchConfig.getBindDn();
131 String bindPassword = CLdapSearchConfig.getBindPassword();
132
133 if ((bindDn != null)) {
134 env.put(Context.SECURITY_AUTHENTICATION, "simple");
135 env.put(Context.SECURITY_PRINCIPAL, bindDn);
136 env.put(Context.SECURITY_CREDENTIALS, bindPassword);
137 }
138
139 try {
140 context = new InitialDirContext(env);
141 if (logger.isDebugEnabled()) {
142 logger.debug("done.");
143 }
144 } catch (NamingException e) {
145 throw new CLdapSearchException("could not open an LDAP connection", e);
146 }
147 }
148
149 /**
150 * Open the context (if needed).
151 * @param logger a logger
152 * @throws CLdapSearchException
153 */
154 private static synchronized void openConnectionIfNeeded(final ALogger logger) throws CLdapSearchException {
155 if (context == null) {
156 openConnection(logger);
157 }
158 }
159
160 /**
161 * Close the context (if needed).
162 * @throws CLdapSearchException
163 */
164 public synchronized void closeConnection() throws CLdapSearchException {
165 if (context != null) {
166 try {
167 context.close();
168 } catch (NamingException e) {
169 throw new CLdapSearchException("could not close an LDAP connection", e);
170 }
171 }
172 context = null;
173 }
174
175 /**
176 * Close the context if needed.
177 * @throws CLdapSearchException
178 * @see java.lang.Object#finalize()
179 */
180 public void finalize() throws CLdapSearchException {
181 closeConnection();
182 }
183
184 }