Wednesday, September 28, 2011

Windows Active Directory Search Library in Java

Hello Every one.

I was updating my Java library for Active directory Searching because of Microsoft Lync server integration with the in-housed belling system. because there is some attributes that you cant get from Lync monitoring server and you need to get it from active directory. and I want to share it with everybody

1.  I created an Enum so i don't bother my self to know which attribute represents what, and not to bother my self regarding case sensitivity below is the Enum

DBName : represents Database fields names
ADName: represents Active directory Attributes names


/**
* Created by Saddam Abu Ghaida
* @author sghaida
*
*/

public enum LDAPAtributesEnum {
    login       ("login",                           "sAMAccountName"),
    email       ("email",                           "mail"),
    first_name ("first_name",                   "givenName"),
    last_name   ("last_name",                    "sn"),
    title              ("title",                               "description"),
    dept       ("dept",                             "department"),
    company              ("company",                       "company"),
    employee_id ("employee_id", "employeeID"),
    location   ("location",                         "l"),
    country ("country", "c"),
    ext                       ("ext",                                "extensionAttribute1"),
    home_tel   ("home_tel",                      "homePhone"),
    home_addr   ("home_addr",                  "streetAddress"),
    emp_id                ("emp_id",                         "employeeID"),
    sip_account ("sip_account",         "msRTCSIP-PrimaryUserAddress"),
    sip_extention ("sip_extention",                 "msRTCSIP-Line"),
    sip_gateway ("sip_gateway",         "msRTCSIP-PrimaryHomeServer"),
    gateway_hostname("gateway_hostname",      "dNSHostName"),
 
    public final String ADName;
    public final String DBName;
 
    LDAPAtributesEnum(String DBName,String ADName) {
this.ADName = ADName;
this.DBName = DBName;
}

}

2.  now the fun part this class will do everything related to search

Note: I'm using GXT BaseModels as a structured output "serialized" because I am writing BaseModels to database directly, but you can customize the output the way you like. if there is some ambiguity in the code. don't hesitate  to comment and i will be more that happy to replay.

in order to be able to run this library in the current shap you need the following

1. GXT-2.2.4-GWT[xx].JAR
2. GWT-SERVLET.JAR
3. JNDI.JAR
4. LDAP.JAR


/**
* Created by Saddam Abu Ghaida
* @author sghaida
*
*/


import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

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.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.security.cert.CertificateException;

import com.extjs.gxt.ui.client.data.BaseModel;

public class ADLib {
   
     /**
     * @param args
     */
   
     @SuppressWarnings("unchecked")
     static     Hashtable<String, String> envGC = new Hashtable();

     static String adminName;
     static String adminPassword;
     static String urlGC;

     static LdapContext ctxGC;

     private String searchBase = "";
     private String searchFilter = "";
   
     String returnedAtts[]={
    "cn",
    "sn",
    "givenName",
    "sAMAccountName",
    "mail","distinguishedName",
    "msRTCSIP-PrimaryUserAddress",
    "msRTCSIP-Line","msRTCSIP-PrimaryHomeServer"};

     private boolean DEBUG=true;
   

     /**
     *
     * @param searchBase search base, e.g. "dc=example,dc=com";
     * @param ADHostName  Host name or IP address of AD Server
     * @param user Username to connect to AD server
     * @param password Password to connecto AD server
     * @throws NamingException
     */
     public ADLib(String searchBase, String ADHostName, String user, String password) throws NamingException
     {
         
           //get AD properties
           this.searchBase = searchBase;
           urlGC = "ldap://" + ADHostName+ ":3268";
           adminName = user;
           adminPassword = password;
         
           envGC.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
           envGC.put(Context.SECURITY_AUTHENTICATION,"simple");
           envGC.put("java.naming.ldap.attributes.binary","userCertificate");
           envGC.put(Context.SECURITY_PRINCIPAL,adminName);
           envGC.put(Context.SECURITY_CREDENTIALS,adminPassword);
          //connect to both a GC
           envGC.put(Context.PROVIDER_URL,urlGC);
       
           //Create the initial directory context for both DC and GC
           ctxGC = new InitialLdapContext(envGC,null);
     }
   
     /**
     * @param name
     * @return list<BaseModel>
     * @throws NamingException
     */
     public List<BaseModel> searchResults(String searchFilter ) throws NamingException
     {
           //Create the search controls      
           SearchControls searchCtls = new SearchControls();
         
           //Specify the attributes to return
           searchCtls.setReturningAttributes(returnedAtts);
               
           //Specify the search scope
           searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
       
           //initialize counter to total the results
           int totalResults = 0;
         
           //Search for objects in the GC using the filter
           NamingEnumeration answer = ctxGC.search(searchBase, searchFilter, searchCtls);
       
           List<BaseModel> results = new ArrayList<BaseModel>();
         
           while (answer.hasMoreElements()) {
             
                SearchResult sr = (SearchResult)answer.next();
                totalResults++;
             
                // Print out some of the attributes, catch the exception if the attributes have no values
             
                Attributes attrs = sr.getAttributes();
                if (attrs != null) {
                     try {
                         
                           NamingEnumeration allAtributes = attrs.getAll();
                           BaseModel bm = new BaseModel();
                           Attribute a;
                         
                           if(DEBUG)System.out.println("-----------------------------------");
                           if(allAtributes != null && allAtributes.hasMore()){
                                while(allAtributes.hasMore()){
                                     a = (Attribute)allAtributes.next();
                                     String name = a.getID();
                                     Object value = a.get();
                                   
                                     if(name.equals("msRTCSIP-Line") && !value.equals(null))
                                         value = ((String)value).replaceAll("tel:", "");
                         
                                     if (name.equals("msRTCSIP-PrimaryUserAddress") && !value.equals(null))
                                    value = ((String)value).replaceAll("sip:", "");
                                   
                                     if (name.equals("msRTCSIP-PrimaryHomeServer") && !value.equals(null))
                                        value = ((String)value).replaceAll("CN=Lc Services,CN=Microsoft,", "");                      
                                                                       
                                     bm.set(name, value);
                                   
                                     String s = "";
                                     try{
                                           if(value!=null && value instanceof String)
                                                s = (String)value;
                                     }catch (Exception e) {
                                           e.printStackTrace();
                                     }
                                     if(DEBUG)System.out.println(name+" = "+s.replaceAll("\\p{Cntrl}", ""));
                                }
                           }
                         
                           results.add(bm);
                     }
                     catch (NullPointerException e)  {
                           System.err.println("Problem listing attributes from Global Catalog: " + e);
                           e.printStackTrace();
                     }
             
                }
   
           }
           ctxGC.close();
           return results;
         
     }
     /**
      * gets LDAP SearchBase for ldap query
      * @return LDAP search base
      */
     public String getSearchBase() {
           return searchBase;
     }

     /**
      * Sets LDAP SearchBase for ldap query
      * @param searchBase
      */
     public void setSearchBase(String searchBase) {
           this.searchBase = searchBase;
     }
   
     /**
      * gets search filter to be used in querying LDAP
      * @return
      */
     public String getSearchFiltter()
     {
    return searchFilter;
     }
   
     /**
      * sets the search filter to be used in querying LDAP
      * @param searchFilter
      */
     public void setSearchFilter(String searchFilter)
     {
    this.searchFilter = searchFilter;
     }

     public boolean isDebug() {
           return DEBUG;
     }

     public void setDebug(boolean debug) {
           this.DEBUG = debug;
     }


     /**
      * Sets the LDAP attributes to be returned to user
      * @return
      */
     public String[] getReturnedAtts() {
           return returnedAtts;
     }

     /**
      * returns the LYNC server hostname/Gateway which is associated with the sip account
      * @param gateway
      * @return
      * @throws NamingException
      */
     public String getGateway(Object gateway) throws NamingException
     {
    String searchFilter = "(distinguishedName=" + ((String)gateway).replaceAll("CN=Lc Services,CN=Microsoft,", "") + ")";      
         String attributes[] = {"dNSHostName"};
         setSearchBase("DC=ccg,DC=resource");
         setReturnedAtts(attributes);
         return searchResults(searchFilter).get(0).get("dNSHostName");
   
     }
   
     /**
      *
      * @param sipAccount
      * @return
      */
     public String getSipAccount(Object sipAccount)
     {
    return ((String)sipAccount).replaceAll("sip:", "");
     }
   
     /**
      *
      * @param sipExtention
      * @return
      */
     public String getSipExtention(Object sipExtention)
     {
    return ((String)sipExtention).replaceAll("tel:", "");
     }
   
     /**
     * Set which attributes to return from the query
     * @param returnedAtts array of attribute names, e.g. {"cn","sn","givenName","sAMAccountName","mail","distinguishedName"}.
     * Set to null to return all of the attributes
     */
     public void setReturnedAtts(String[] returnedAtts) {
           this.returnedAtts = returnedAtts;
     }

     /**
     * @param args
     * @throws CertificateException
     * @throws NamingException
     */
    public static void main(String[] args) throws CertificateException, NamingException {
         
         
           ADLib connector = new ADLib("dc=example,dc=com", "1.1.1.1", "CN=sghaida, CN=Users, DC=example, DC=com", "xxxxxxx");
       
           //specify the LDAP search filter
           connector.setSearchBase("dc=example,dc=com");
         
           //String searchFilter = "(&(&(objectClass=user)(!(objectClass=contact)))(!(objectClass=computer)))";
           String searchFilter = "(&(objectClass=msRTCSIP-Pool)(cn=1:1))";
           String attributes[]={LDAPAtributesEnum.gateway_hostname.ADName};
           connector.setReturnedAtts(attributes);
           //String attributes[]={LDAPAtributesEnum.first_name.ADName, LDAPAtributesEnum.last_name.ADName, "mail",LDAPAtributesEnum.dept.ADName};
           List<BaseModel> results = connector.searchResults(searchFilter);
       
     }

}








No comments:

Post a Comment