JNDI

I l @ ve RuBoard

Now you're ready to talk to LDAP from Java. To do this, you use the Java Naming and Directory Interface (JNDI). JNDI can be used for a lot more than just interfacing to LDAP. For example, you can use JNDI to talk to DNS. But for now, our discussion will be restricted to JNDI as it pertains to LDAP.

JNDI itself doesn't know anything about LDAP. Instead, it provides a general interface that lets a programmer talk to a number of different resources (such as NIS, LDAP, or DNS) using the same API. What all these have in common is the notion that a name can be looked up in some kind of directory to return information about that name. For example, in DNS, a name maps to an IP address. In LDAP, a name (represented as a DN or an RDN) maps to an LDAP object with attributes and possibly child objects.

Directory services such as LDAP register themselves with JNDI as providers. When you request an initial context from JNDI, you specify which service you want to use.

A context is a relative reference into a JNDI tree. For example, in LDAP, the initial context that JNDI returns is the root of the LDAP database (in this case, o=bfg.com ). From there, you can use an RDN to find a child of the current object without needing to refer to the entire DN.

It is also possible to talk directly to LDAP without using JNDI, using tools such as the Novel LDAP Class Libraries. Although there is nothing wrong with this approach, most developers have chosen to use the JNDI interface instead.

In almost all cases when interfacing to an LDAP server, you want to be able to do four things to an LDAP server: search it, get an entry, modify an entry, and add an entry. You can do these four things very easily by using the JNDI API directly (see Listing 15.3).

Listing 15.3 Employee.java
 package com.bfg.employee; import java.util.Hashtable; import javax.naming.*; import javax.naming.directory.*; import java.util.Vector; import java.util.HashMap; import java.sql.*; import java.util.Iterator; import org.apache.turbine.services.db.TurbineDB; import org.apache.turbine.util.db.pool.DBConnection; import org.apache.log4j.Category; import java.util.ResourceBundle; public class Employee implements java.lang.Comparable {     static Category cat = Category.getInstance(Employee.class);     protected String pFirstName;     public String getFirstName() {      return pFirstName;     }     public void setFirstName(String firstName) {      pFirstName = firstName;     }     protected String pLastName;     public String getLastName () {      return pLastName;     }     public void setLastName (String lastName) {      pLastName = lastName;     }     protected String pUserID;     public String getUserID () {      return pUserID;     }     public void setUserID (String userID) {      pUserID = userID;     }     protected String pPassword;     public String getPassword () {      return pPassword;     }     public void setPassword (String password) {      pPassword = password;     }     protected String pOrganization;     public String getOrganization () {      return pOrganization;     }     public void setOrganization (String org) {      pOrganization = org;     }     protected String pOrgUnit;     public String getOrgUnit() {      return pOrgUnit;     }     public void setOrgUnit(String ou) {      pOrgUnit = ou;     }     protected String pEmployeeNumber;     public String getEmployeeNumber () {      return pEmployeeNumber;     }     public void setEmployeeNumber (String empno) {      pEmployeeNumber = empno;     }     protected String pTelephone;     public String getTelephoneNumber() {      return pTelephone;     }     public void setTelephoneNumber(String telno) {      pTelephone = telno;     }     protected String pTitle;     public String getTitle() {      return pTitle;     }     public void setTitle(String title) {      pTitle = title;     }     public static Employee findEmployee(String userID) {      Vector employees = runEmployeeSearch("(uid=" + userID + ")");      if (employees.size() > 0) {      return((Employee) employees.elementAt(0));      }  else {           return null;      }     public void createEmployee() throws NamingException {      Hashtable env = new Hashtable();      env.put(Context.INITIAL_CONTEXT_FACTORY,              "com.sun.jndi.ldap.LdapCtxFactory");      env.put(Context.PROVIDER_URL,              "ldap://localhost:389/");      env.put(Context.SECURITY_AUTHENTICATION, "simple");      env.put(Context.SECURITY_PRINCIPAL, "cn=chiefgeek,dc=bfg,dc=com");      env.put(Context.SECURITY_CREDENTIALS, "GeekGuru");      DirContext ctx = new InitialDirContext(env);      Attributes myAttrs;      String uid = getFirstName().substring(0,1) + getLastName();      uid = uid.toLowerCase();      myAttrs = new BasicAttributes(true);      Attribute oc = new BasicAttribute("objectclass");      oc.add("top");      oc.add("inetOrgPerson");      myAttrs.put(oc);      myAttrs.put("uid", uid);      myAttrs.put("cn", getFirstName() + " " + getLastName());      myAttrs.put("givenname", getFirstName());      myAttrs.put("sn", getLastName());      myAttrs.put("o", getOrganization());      myAttrs.put("ou", getOrgUnit());      myAttrs.put("userPassword", getPassword());      myAttrs.put("telephoneNumber", getTelephoneNumber());      myAttrs.put("employeeNumber", getEmployeeNumber());      myAttrs.put("title", getTitle());      boolean success = false;      int count = 0;      String uidnum = uid;      while (!success) {          try {              ctx.createSubcontext("uid=" + uidnum + ",dc=bfg,dc=com", myAttrs);              success = true;          }  catch (NameAlreadyBoundException e) {               count++;               uidnum = uid + count;               myAttrs.put("uid", uidnum);          }      }      ctx.close();      setUserID(uidnum);     }     public void modifyEmployee() throws NamingException {      Hashtable env = new Hashtable();      env.put(Context.INITIAL_CONTEXT_FACTORY,              "com.sun.jndi.ldap.LdapCtxFactory");      env.put(Context.PROVIDER_URL,              "ldap://localhost:389/");      env.put(Context.SECURITY_AUTHENTICATION, "simple");      env.put(Context.SECURITY_PRINCIPAL, "cn=chiefgeek,dc=bfg,dc=com");      env.put(Context.SECURITY_CREDENTIALS, "GeekGuru");      DirContext ctx = new InitialDirContext(env);      Attributes myAttrs;      myAttrs = new BasicAttributes(true);      myAttrs = new BasicAttributes(true);      Attribute oc = new BasicAttribute("objectclass");      oc.add("top");      oc.add("inetOrgPerson");      myAttrs.put(oc);      myAttrs.put("uid", getUserID());      myAttrs.put("cn", getFirstName() + " " + getLastName());      myAttrs.put("givenname", getFirstName());      myAttrs.put("sn", getLastName());      myAttrs.put("o", getOrganization());      myAttrs.put("ou", getOrgUnit());      myAttrs.put("userPassword", getPassword());      myAttrs.put("telephoneNumber", getTelephoneNumber());      myAttrs.put("employeeNumber", getEmployeeNumber());      myAttrs.put("title", getTitle());      ctx.modifyAttributes("uid=" + getUserID() +",dc=bfg,dc=com",                           DirContext.REPLACE_ATTRIBUTE,                           myAttrs);      ctx.close();     }     public boolean equals(Employee e) {      return (getUserID() != null) && (e.getUserID() != null)          && getUserID().equals(e.getUserID());     }     public static Vector getAllEmployees() {      return runEmployeeSearch("(objectclass=inetOrgPerson)");     }     public static Vector runEmployeeSearch(String search) {      Vector employees = new Vector();      try {          Hashtable env = new Hashtable();          env.put(Context.INITIAL_CONTEXT_FACTORY,                  "com.sun.jndi.ldap.LdapCtxFactory");          env.put(Context.PROVIDER_URL,          "ldap://localhost:389/");          env.put(Context.SECURITY_AUTHENTICATION, "simple");          env.put(Context.SECURITY_PRINCIPAL, "cn=chiefgeek,dc=bfg,dc=com");          env.put(Context.SECURITY_CREDENTIALS, "GeekGuru");          DirContext ctx = new InitialDirContext(env);          SearchControls constraints = new SearchControls();          constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);          NamingEnumeration results =              ctx.search("dc=bfg, dc=com", search, constraints);          while (results != null && results.hasMore()) {              Employee e = new Employee();              SearchResult sr = (SearchResult) results.next();              Attributes attrs = sr.getAttributes();              e.setFirstName((String)attrs.get("givenname").get());              e.setLastName((String)attrs.get("sn").get());              e.setPassword(new String(((byte[])attrs.get("userPassword").get())));              e.setUserID((String)attrs.get("uid").get());              e.setOrganization((String) attrs.get("o").get());              e.setOrgUnit((String) attrs.get("ou").get());              e.setTelephoneNumber((String) attrs.get("telephoneNumber").get());              e.setTitle((String) attrs.get("title").get());              e.setEmployeeNumber((String) attrs.get("employeeNumber").get());              employees.add(e);          }          ctx.close();       }  catch (NamingException ex) {            System.err.println("Problem getting attribute:" + ex);            ex.printStackTrace();      }      return employees;     }     public int compareTo(Object o) {      Employee e = (Employee) o;      int  comp = getLastName().compareTo(e.getLastName());      if (comp != 0) {          return comp;      }      return getFirstName().compareTo(e.getFirstName());     } } 

It's always nice to implement Comparable for object classes such as employees that you might want to sort in lists. This means that you can use the built-in Java sorting functionality on them.

You need to provide object properties for any attributes that you want to store and retrieve, just as you would for an object that is sourced from a database.

You're going to write a generalized method to find one or more employees based on an LDAP filter, so here you only have to call the search method with the appropriate filter and then see if you get an employee record.

With record creation, you get into the interesting stuff. You begin by instantiating a JNDI context that points to your LDAP server. You need to provide authentication because you're adding information; this requires nonanonymous privileges (you'll also need this when reading data back out because you want the password, which is normally concealed).

In LDAP, you can control what operations can be done by anyone (similar, for example, to doing an anonymous FTP) and what operations require authentication. By default, insertion of records can't be done without providing authentication.

After you've established a context, you need to generate a user ID. You don't want to have the person creating the account specify the ID because the user ID is the unique part of the DN for an employee; you can't have two jsmith entries if there is a John Smith and a James Smith, so you'll need to have the code check for that. Make the user ID the first letter of the first name and the entire last name.

Go through and set all the attributes for the new object. If an attribute has two values, such as objectclass , create another attribute object, put the values in it, and then add that object to the main attribute object.

With all the attributes in place, the code enters a loop. It tries to create a new subcontext of the JNDI context (which, for LDAP contexts, means that it creates a new LDAP record). If it gets a NameAlreadyBound exception, this means that that DN is already in use. In that case, the code appends a 1 to the end of the user ID (jsmith1, for example) and loops around to try again. If the DN is still in use, it tries 2 , 3 , and so forth until one succeeds.

When you get a good insertion, set the uid record of this employee to the value that worked, and then return.

Modifying an existing user uses essentially the same code, except that it calls modifyAttributes instead of createSubcontext . The REPLACE_ATTRIBUTE flag indicates that you should overwrite an attribute of the same name rather than adding to it.

The getAllEmployees method also uses the search method, which directly follows it. It requests all objects of type inetOrgPerson , which is the object class that you used to define the employees.

The employee search method is handed an LDAP search string and sets the search constraints to search the entire LDAP tree (you also can request one-level or root-only searches).

When matches are found, all the attributes are copied out of the LDAP record into the appropriate properties in the object.

The compareTo method just tries comparing the last names and then compares the first names if the last names are equals.

I l @ ve RuBoard


MySQL and JSP Web Applications. Data-Driven Programming Using Tomcat and MySQL
MySQL and JSP Web Applications: Data-Driven Programming Using Tomcat and MySQL
ISBN: 0672323095
EAN: 2147483647
Year: 2002
Pages: 203
Authors: James Turner

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net