package com.tm.jndi.ldap;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.NameAlreadyBoundException;
import javax.naming.directory.*;
import java.util.*;

public class JndiLdapConnection
{
  private String url;
  private String user;
  private String password;
  private String initialContextFactory;
  private String dn;
  protected InitialContext context;
  private String contextRoot;
  private String dnSuffix;
  private boolean debug = false;
  private String debugSystemProperty = "com.tm.jndi.ldap.debug"; 
  private String resourceBundleName = "com.tm.jndi.ldap.JndiLdapConnection";
  public JndiLdapConnection()
  {
    initFromResourceBundle();
    this.url = new String("");
    this.user = new String("");
    this.password = new String("");
    this.dn = new String("");
    String debugProperty = System.getProperty("debugSystemProperty");
    if(debugProperty != null && debugProperty.equals("true")) {
      this.debug = true;
    }
  }
  
  public JndiLdapConnection(	String url,
				String user,
				String password)
  {
    initFromResourceBundle();
    this.url = url;
    this.user = user;
    this.password = password;
    this.dn = "cn=" + user + dnSuffix;
    String debugProperty = System.getProperty(debugSystemProperty);
    if(debugProperty != null && debugProperty.equals("true")) {
      this.debug = true;
    }
  }

  public JndiLdapConnection(	String host,
  				String port,
				String contextRoot,
				String user,
				String password)
  {
    initFromResourceBundle();
    this.url = "ldap://" + host + ":" + port + "/" + contextRoot;
    this.user = user;
    this.password = password;
    this.contextRoot = contextRoot;
    //Was the username passed in as a uername or fully qualified?
    if( user.substring(0,3).equals("cn=")) {
      
      this.dn = user;
    } else {
      this.dn = "cn=" + user + dnSuffix;
    }
    String debugProperty = System.getProperty(debugSystemProperty);
    if(debugProperty != null && debugProperty.equals("true"))
    {
      this.debug = true;
    }
  }

  private void initFromResourceBundle()
  {
    try {
      ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName);
      this.contextRoot= rb.getString("contextRoot");
      this.dnSuffix = rb.getString("dnSuffix");
      this.initialContextFactory= rb.getString("initialContextFactory");
    } catch (Exception e) { 
      e.printStackTrace();
    } 
  }

  public synchronized void connect(  	String host,
                                	String port,
                                	String contextRoot,
                                	String user,
                                	String password)
    throws ConnectionException
  {
    this.url = "ldap://" + host + ":" + port + "/" + contextRoot;
    this.user = user;
    this.password = password;
    this.contextRoot = contextRoot;
    if( user.substring(0,3) == "cn=") {
      this.dn = user;
    } else {
      this.dn = "cn=" + user + dnSuffix;
    }
    connect();
  }

  public synchronized void connect(	String url, 
					String user, 
					String password)
    throws ConnectionException
  {
    this.url = url;
    this.user = user;
    this.password = password;
    connect();
  }

  protected synchronized void connect()
    throws ConnectionException
  {
    Hashtable env = new Hashtable();
    try {
      env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
      env.put(Context.PROVIDER_URL, url);
      env.put(Context.SECURITY_PRINCIPAL, dn);
      env.put(Context.SECURITY_CREDENTIALS, password);
      if(debug) 
      {
        System.out.println("icf=" + initialContextFactory);
        System.out.println("url=" + url);
        System.out.println("dn=" + dn);
        System.out.println("password=" + password);
      }
      context = new InitialDirContext(env);
      if(context != null && debug)
      {
        System.out.println("Context object appears to be valid.");
      }
    }
    catch (NamingException e) {
      e.printStackTrace();
      throw new ConnectionException();
    }
    return;
  }
  public synchronized void close()
  {
    try {
      context.close();
    } 
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }  
}
