package com.cf.common.ldap;

import java.util.Hashtable;

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

import com.cf.common.constants.CommuForceConstants;

public class CFLdapClient {
	
	public static boolean authenticateWithDN(String dn, String password) {
		 	Hashtable<Object,String> env = new Hashtable<Object,String>();
	        env.put(Context.INITIAL_CONTEXT_FACTORY, CommuForceConstants.LDAP_CONTEXT_FACTORY);
	        env.put(Context.PROVIDER_URL, "ldap://localhost:10389/o=commuForce");

	        env.put(Context.SECURITY_AUTHENTICATION, CommuForceConstants.LDAP_AUTHENTICATION_TYPE);
	        env.put(Context.SECURITY_PRINCIPAL, dn);
	        env.put(Context.SECURITY_CREDENTIALS, password);

	        try {
	            Context ctx = new InitialContext(env);
	            NamingEnumeration enm = ctx.list("");

	            while (enm.hasMore()) {
	                System.out.println(enm.next());
	            }

	            enm.close();
	            ctx.close();
	        } catch (NamingException e) {
	            System.out.println(e.getMessage());
	            e.printStackTrace();
	            return false;
	        }
	        return true;
	}
	
	public static boolean authenticateWithUID(String uid, String password) {
		Hashtable<Object,String> env = new Hashtable<Object,String>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, CommuForceConstants.LDAP_CONTEXT_FACTORY);
        env.put(Context.PROVIDER_URL, "ldap://localhost:10389/");
        env.put(Context.SECURITY_AUTHENTICATION, CommuForceConstants.LDAP_AUTHENTICATION_TYPE);

        DirContext ctx = null;

        try {            
            // Step 1: Bind anonymously            
            ctx = new InitialDirContext(env);

            // Step 2: Search the directory
            String base = "o=commuForce";
            String filter = "(&(objectClass=inetOrgPerson)(uid={0}))";           
            SearchControls ctls = new SearchControls();
            ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            ctls.setReturningAttributes(new String[0]);
            ctls.setReturningObjFlag(true);
            NamingEnumeration enm = ctx.search(base, filter, new String[] { uid }, ctls);

            String dn = null;

            if (enm.hasMore()) {
                SearchResult result = (SearchResult) enm.next();
                dn = result.getNameInNamespace();

                System.out.println("dn: "+dn);
            }

            if (dn == null || enm.hasMore()) {
                // uid not found or not unique
                throw new NamingException("Authentication failed");
            }

            // Step 3: Bind with found DN and given password
            ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, dn);
            ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
            // Perform a lookup in order to force a bind operation with JNDI
            ctx.lookup(dn);
            System.out.println("Authentication successful");

            enm.close();
        } catch (NamingException e) {
            System.out.println(e.getMessage());
            return false;
        } finally {
            try {
				ctx.close();
			} catch (NamingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			}
        }
        return true;
	}
	
	public static void main(String args[]) {
		//authenticateWithDN("cn=James Hook,ou=people,o=commuForce", "peterPan");
		authenticateWithUID("Peter", "peterPan");
	}
}
