JNDI ldap search recursive

1.4k views Asked by At

Can anyone help me to improve the ldap recursive search from java? Below is my code. The filter I am passing is filter=(&(IMSI=404201234500021)). Currently it's taking more than 19 sec to search one record from 100000 total records.

public List<Map<String, String>> searchRecursive(List<String> sColumns, Map<String, String> searchFilters, int startIndex,
        int amount)
{
    String searchRDN = "";
    List<Map<String, String>> items = new ArrayList<Map<String, String>>();
    Attributes searchAttributes = new BasicAttributes();
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);

    NamingEnumeration<SearchResult> results = null;
    try
    {
             String filter = "";
             if (searchFilters != null)
             {
                 for (Map.Entry<String, String> entry : searchFilters.entrySet())
                 {
                     filter += "(" + entry.getKey() + "=" + entry.getValue() + ")";
                 }
             }    
            filter = "(&" + filter + ")";
            _log.debug("filter="+filter);
            byte[] cookie = null;
            ctx.setRequestControls(new Control[]
                {new PagedResultsControl(amount, cookie, Control.NONCRITICAL)});

           //results = ctx.search(searchRDN, searchAttributes, null);
            results= ctx.search("", filter, ctls);
        if (results != null)
        {
            while (results.hasMore())
            {
                Map<String, String> rowSet = new CaseInsensitiveMap();
                SearchResult searchResult = results.next();
                String rdn = searchResult.getNameInNamespace();
                rowSet.put("baseRDN", rdn);
                NamingEnumeration<? extends Attribute> all = searchResult.getAttributes().getAll();
                while (all.hasMoreElements())
                {
                    Attribute attr = all.nextElement();
                    // attr.getID()
                    NamingEnumeration<?> all2 = attr.getAll();
                    String value = "";
                    while (all2.hasMoreElements())
                    {
                        if (!value.equals(""))
                        {
                            value += ", " + all2.nextElement();
                        }
                        else
                        {
                            value = "" + all2.nextElement();
                        }
                    }
                    rowSet.put(attr.getID(), value);
                }
                items.add(rowSet);
            }
        }
    }
    catch (Throwable e)
    {
        _log.error(e.getMessage());
        _log.debug(e);
    }
    finally
    {
        if (results != null)
        {
            try
            {
                results.close();
            }
            catch (Exception e)
            {
            }
        }
    }
    return items;
}
1

There are 1 answers

10
barthel On

Depending on the LDAP tree and data structure may one or more of the following tips will be useful:

  1. Start the search at a specific ou= instead at root and reduce the search depth.

    Replace "" in ctx.search("", filter, ctls); with a DN like ou=people,ou=company,ou=com

  2. Limit the search result size.

    Add a search result size via ctls.setCountLimit(expected);

  3. Limit the collected attributes

    Add a set of attributes you are interested in.

    String[] attributeFilter = { "cn", "mail" }; ctls.setReturningAttributes(attributeFilter);

EDIT to explain 1.

The LDAP structure is like a tree:

root
 +- dc=com
  +- dc=company
   +- dc=people
    +- ou=developer
     +- dn=john_doe
    +- ou=manager
     +- dn=jane_foo

If you are searching for john_doe start recursive search at ou=developer,ou=people,ou=company,ou=com instead of root (representing by "" in your code).

EDIT example based on comment

root
 +- dc=com
  +- dc=example
   +- IMSI=1
    +- IMSI=1
     +- Context-Identifier=1001

This data structure looks strange to me. But based on these information the search should start at IMSI=1,dc=example,dc=com.