Showing posts with label Global Catalog. Show all posts
Showing posts with label Global Catalog. Show all posts

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);
       
     }

}