
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Iterator;
import javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
//import javax.naming.ldap.LdapName;
import javax.naming.Context;
import junit.framework.TestCase;
import net.etouch.wikiReg.util.RegProperties;

//import org.apache.log4j.Logger;

/**
 * @author J?rg Henne
 */
public class TestHang extends TestCase {
  private class MyRunner extends Thread {
    public Exception yikes;

    /*
     * @see java.lang.Thread#run()
     */
    public void run() {
      try {
        //xtestSingleThreadedKeepLingeringCtx();
		//xtestMultiThreaded();
		createAndDelete();
      } catch (Exception e) {
        yikes = e;
      }
    }
  }

//  private static final Logger logger = Logger.getLogger(TestHang.class);

  int count;

  private Hashtable env;

  boolean keepLingeringSubcontexts = false;

  int objCounter;

  /**
   * @param name
   * @throws NamingException
   */
  private void create(String name) throws NamingException {
    InitialDirContext ctx = new InitialDirContext(getEnv());
//	DirContext ctx = RegProperties.getRootContext() ;
    try {
      BasicAttributes a = new BasicAttributes();
      BasicAttribute oc = new BasicAttribute("objectClass");
      String ocs[] = {"top", "organizationalUnit"};
      for (int i=0; i<ocs.length; i++)
	  {
		  String c = ocs[i];
        oc.add(c);
	  }
      a.put("description", "Just a test");
      a.put(oc);

      System.out.println("create: " + name);
      if (keepLingeringSubcontexts)
        ctx.createSubcontext(name, a); // yes, I know, missing close().
      else
        ctx.bind(name, null, a);
    } finally {
      ctx.close();
    }
  }

  private void createAndDelete() throws NamingException {
    List toBeDeleted = new LinkedList();
    for (int i = 0; i < 10; i++) {
      int n;
      synchronized (this) {
        n = count++;
      }

      String name = "ou=someTestOU" + n;
      create(name);
      toBeDeleted.add(name);
    }
	Iterator it = toBeDeleted.iterator();
    while(it.hasNext()) {
		String name = (String)it.next();
      delete(name);
    }
  }

  /**
   * @param name
   * @throws NamingException
   */
  private void delete(String name) throws NamingException {
    InitialDirContext ctx = new InitialDirContext(getEnv());
//	DirContext ctx = RegProperties.getRootContext() ;

    try {
      System.out.println("delete: " + name);
      ctx.unbind(name);
    } finally {
      ctx.close();
    }
  }

  private void deleteRecursively(DirContext ctx, Name name)
      throws NamingException {
    NamingEnumeration children = ctx.list(name);
    try {
      while (children.hasMore()) {
        NameClassPair child = (NameClassPair)children.next();
        name.add(child.getName());
        deleteRecursively(ctx, name);
        name.remove(name.size() - 1);
      }
    } finally {
      children.close();
    }

    System.out.println("del " + name);

    if (name.size() > 0)
      ctx.unbind(name);
  }

  /**
   * @return
   */
  private Hashtable getEnv() {
    if (null == env) {
      env = new Hashtable();
      env
          .put("java.naming.factory.initial",
              "com.sun.jndi.ldap.LdapCtxFactory");
      env.put("java.naming.provider.url",
          "ldap://192.168.0.29:10489/ou=unittest,dc=example,dc=com");
      env.put("java.naming.security.authentication", "none");
      env.put("com.sun.jndi.ldap.connect.pool", "true");
		env.put(Context.SECURITY_PRINCIPAL, RegProperties.getProperty(RegProperties.CONTAINER_PRINCIPAL));
    	env.put(Context.SECURITY_CREDENTIALS, RegProperties.getProperty(RegProperties.CONTAINER_CREDENTIALS));
    	env.put(Context.SECURITY_AUTHENTICATION, "simple");    



    }
    return env;
  }
  /*
   * @see junit.framework.TestCase#setUp()
   */
  protected void setUp() throws Exception {
    super.setUp();

    InitialDirContext ctx = new InitialDirContext(getEnv());
//	DirContext ctx = RegProperties.getRootContext() ;

//    deleteRecursively(ctx, new LdapName(""));
    deleteRecursively(ctx, new javax.naming.CompositeName("") );
    ctx.close();
    
    keepLingeringSubcontexts = false;
  }

 public void testSingleThreaded() throws Exception {
	  	  System.out.println(" =============== xtestSingleThreaded ===================== ");
    for (int i = 0; i < 100; i++) {
      createAndDelete();
    }
  }

  public void testMultiThreaded() throws Exception {
	  System.out.println(" =============== testMultiThreaded ===================== ");
    List threads = new LinkedList();
    for (int i = 0; i < 10; i++) {
      MyRunner r = new MyRunner();
      r.start();
      threads.add(r);
    }
	Iterator it = threads.iterator();
    while(it.hasNext()) {
		MyRunner r = (MyRunner)it.next();
      r.join();
      if (r.yikes != null)
        throw r.yikes;
    }
  }

 

  public void testSingleThreadedKeepLingeringCtx() throws Exception {
	  	  System.out.println(" =============== xtestSingleThreadedKeepLingeringCtx ===================== ");
    keepLingeringSubcontexts = true;
    for (int i = 0; i < 100; i++) {
      createAndDelete();
    }
  }
}
