/*
ESUP-portail is a french academic project developed under the GPL (General Public License) augmented according to the following :
A binary or source file developped by ESUP-portail can be used or compiled with products under Apache license.
The official english text of the GPL can be found here : http://www.gnu.org/licenses/gpl.html .
A non official french translation can be found here : http://www.linux-France.org/article/these/gpl.html .
The different kinds of licenses governing the products developed by the Apache foundation can be found here : http://www.apache.org/licenses .
It follows that you can as well as use download contents as well modify and redistribute them provided you respect the GPL terms.
Downloading and using such contents do not provide any guaranty.
Be sure that you have well understood the terms of the license before using the contents it covers.
The ESUP-portail distribution includes the following distributions :
    * UPortal :
      software developed by JA-SIG (Java Architecture - Special Interest Group)
      You can find the license page here : http://mis105.udel.edu/ja-sig/uportal/license.html
    * CAS :
      SSO solution developed by Yale University
      You can find the project page here : http://www.yale.edu/tp/auth
    * Cocoon :
      XML framework distributed by the Apache foundation under Apache license;
      Please find the full text here : http://cocoon.apache.org/2.1/license.html
    * Mod_dav:
      A DAV module for Apache web server
      You can find the project page here : http://www.webdav.org/mod_dav
    * IMP :
      webmail from Horde application framework
      You can find the project page here : http://www.horde.org
    * …. To be completed
*/
package org.esupportail.portal.channels.CStockage.userManagement;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
 * Id: LdapUsersManagement.java,v 1.0 15 oct. 2004
 * Copyright (c) 2004 Esup Portail (www.esup-portail.org)
 * Classes: LdapUsersManagement
 * Original Author: Yohan Colmant
 * Manage the ldap users. 
 */
public class LdapUsersManagement {


	/**
	 * Logger object
	 */
	protected static final Log log = LogFactory.getLog(LdapUsersManagement.class);
	
	private static Hashtable displayNames = new Hashtable();
	
	/**
	 * Get a user display name from its key
	 * @param serverUrl url of the ldap server
	 * @param baseDn the base dn for the search
	 * @param bindDn the dn used to bind to the ldap
	 * @param bindPassword the password used to bind to the ldap
	 * @param attributeKey the attribute key. for example, it is the attribute containing the user key in the ldap
	 * @param attributeValue the user key
	 * @param displayNameAttribute the display name attribute in the server
	 * @return the good display name
	 * @throws NamingException
	 */
	public static String getUserDisplayName(String serverUrl, String baseDn, String bindDn, String bindPassword, String attributeKey, String attributeValue, String displayNameAttribute) throws NamingException {
		
		String ret = null;
		
		String cachedDisplayname = getCachedDisplayName(attributeValue);
		// is DisplayName in cache
		if (cachedDisplayname != null) {
			ret = cachedDisplayname;
		}
		else {
			
			// connexion
			Hashtable env = new Hashtable();
			env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
			env.put(Context.PROVIDER_URL, serverUrl);
			
			// simple authentication
			if ( (bindDn == null || bindDn.trim().equals("")) && (bindPassword == null || bindPassword.trim().equals(""))) {
				env.put(Context.SECURITY_AUTHENTICATION, "none");
			}
			else {
				env.put(Context.SECURITY_AUTHENTICATION, "simple");
				env.put(Context.SECURITY_PRINCIPAL, bindDn);
				env.put(Context.SECURITY_CREDENTIALS, bindPassword);
			}
			
			// context access
			DirContext context = new InitialDirContext(env);
				
			SearchControls constraints = new SearchControls();
			constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
			
			// filter: we the good key
			String filter="("+attributeKey+"="+attributeValue+")";
			
			// launch the search
			NamingEnumeration ne = context.search(baseDn, filter, constraints);
				
			// for each element
			if (ne.hasMoreElements()) {
					
				// get the element
				SearchResult searchRes = (SearchResult)ne.nextElement();
				
				// each attribute of this user
				Attributes atts = searchRes.getAttributes();
				
				// get the good attribute
				Attribute att = atts.get(displayNameAttribute);
				if (att == null) {
					throw new NamingException();
				}
				else {
					// get this attribute values
					NamingEnumeration iter = att.getAll();
					if (iter.hasMoreElements()) {
						ret = (String)iter.nextElement();
						setCachedDisplayName(attributeValue, ret);
					}
				}			
			}
			
		}


		if (ret==null) {

			// log
			if (log.isDebugEnabled()){
				log.debug("getUserDisplayName"+" :: value \""+attributeValue+"\" not found in the LDAP for the key \""+attributeKey+"\" and dn=\""+baseDn+"\"");
			}
			
			throw new NamingException();
		}
		else {
			return ret;
		}
		
	}
		
		

	/**
	 * set cachedDisplayname
	 * @param key of DispalyName to return
	 * @return cachedDisplayname
	 */
	private static synchronized String getCachedDisplayName(String key) {
		if (log.isDebugEnabled()){
			log.debug("getCachedDisplayName :: get from cache: "+key);
		}
		return (String)displayNames.get(key);
	}

	/**
	 * get cachedDisplayname
	 * @param key of displayName to cahe
	 * @param value of displayName to cahe
	 */
	private static synchronized void setCachedDisplayName(String key, String value) {
		if (log.isDebugEnabled()){
			log.debug("setCachedDisplayName :: set in cache: "+key+" --> "+value);
		}
		displayNames.put(key, value);
	}
	
	
	
    
	
	
}
