Tivoli Directory Integrator

Hi all,

Lately I’ve been playing with Tivoli Directory Integrator (TDI). One thing I’ve noticed is that you cannot loop through all LDAP entries with a single query - the server stops you at a maximum query limit. A quick search reveals that TDI has paging parameters for an LDAP search. Hurray! Small problem though - there isn’t anywhere you can input what page you want. Kind of a let down. Google is of no help either.

Tivoli Directory Integrator

However, I have mashed together some Java/LDAP example code from the LDAP docs. This involves setting a few Paged Control attributes on the connector when it has run out of entries.

Firstly, we need to grab the connector from TDI and stash it away in JavaScript so we can refer to it later (we could grab it every time, but this way is more efficient). In the After Initialize hook on your LDAP iterator, add:

// * After Initialize *
// the LDAP connector
var ldapConnector = task.getConnector("get object from ldap").getConnector();

// number of entries per page we have set up in the connector object
var pageSize = 10;

Next, we need to hook in to After GetNext to check if the connector has run out of entries (before TDI notices and finishes the iteration - trying to change the page in the End Of Data hook is a waste of time). In the hook we use the code as per the link above to grab the page result cookie and insert it in to a new paged results control in order to get to the next page. I have added a simple “peek” style check to see if the connector is out of results as I could not find a hasMoreEntries() method anywhere.

// * After GetNext *
// check to see if the LDAP connector has run out of entries
var nextEntry = ldapConnector.getNextEntry();
if (nextEntry != null)
{
 // connector still has entries, put it back and let the assembly line
 // continue
 ldapConnector.pushback(nextEntry);
}
else
{
 // connector has run out of entries
 // reset the context request controls before TDI itself checks to see if
 // there are entries left

 /* LdapContext */
 var ctx = ldapConnector.getLdapContext();
 var cookie = null;

 /* Control[] */
 var controls = ctx.getResponseControls();
 if (controls != null)
 {
  for (var i = 0; i < controls.length; ++i)
  {
   if (typeof controls[i] == "javax.naming.ldap.PagedResultsResponseControl")
   {
    /* PagedResultsResponseControl */
    var prrc = controls[i];
    cookie = prrc.getCookie();
    break;
   }
  }
 }
 // Re-activate paged results
 var newControlArray = java.lang.reflect.Array.newInstance(
  javax.naming.ldap.Control, 1);
 newControlArray[0] = new javax.naming.ldap.PagedResultsControl(
  pageSize, cookie, javax.naming.ldap.Control.CRITICAL);
 ctx.setRequestControls(newControlArray);
}

Ta-da! You now have an unlimited number of LDAP entries coming out of your LDAP connector.

Notes:

  • You should choose a number greater then 10 for your page size. That page size is a tad small, causing more traffic than required.
  • Retrieving the page size from the connector itself would be better than having it re-written in JavaScript and therefore having it in two locations, however I’m not sure how to do that.