Details

    • Type: Wish Wish
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.0.0-M21
    • Fix Version/s: 1.0.0-M22
    • Labels:
      None

      Description

      I originally wanted to impletent DirSync Control using Apache API. After I looked into existing Controls under org.apache.directory.api.ldap.model.message.controls. I think it's difficult to me. I can't understand the decoding and encoding of controls specification of Apache. So I want Apache team give implementation for this control. Details for this control, please refer to http://msdn.microsoft.com/en-us/library/ms677626(v=vs.85).aspx.

        Activity

        Hide
        Emmanuel Lecharny added a comment -

        We can implement this control, but we need an exact description of it. The MS page only contain some vague informatons about it. The crtical part is the ASN/1 description of this control.

        Show
        Emmanuel Lecharny added a comment - We can implement this control, but we need an exact description of it. The MS page only contain some vague informatons about it. The crtical part is the ASN/1 description of this control.
        Hide
        Emmanuel Lecharny added a comment - - edited

        The Control payload is something like :

        DirSync SEQUENCE

        { flags INTEGER, maxBytes INTEGER, cookie OCTET STRING }
        Show
        Emmanuel Lecharny added a comment - - edited The Control payload is something like : DirSync SEQUENCE { flags INTEGER, maxBytes INTEGER, cookie OCTET STRING }
        Hide
        Robert Hou added a comment - - edited

        The standard description for this control is on http://tools.ietf.org/html/draft-armijo-ldap-dirsync-01

        Show
        Robert Hou added a comment - - edited The standard description for this control is on http://tools.ietf.org/html/draft-armijo-ldap-dirsync-01
        Hide
        Robert Hou added a comment -

        Hi Emmanuel,
        Which revision do you plan to implement this control in? is 1.0.0-M22? If yes, when will it be released?
        thanks,
        -Robert

        Show
        Robert Hou added a comment - Hi Emmanuel, Which revision do you plan to implement this control in? is 1.0.0-M22? If yes, when will it be released? thanks, -Robert
        Hide
        Emmanuel Lecharny added a comment -

        I'm currently implementing the control. It will be ready tomorrow, I think.

        The idea is to get M22 out by the end of this week-end.

        Ideally, you'll need to test it as soon as it's in the code (I'll inform you in this JIRA)

        Show
        Emmanuel Lecharny added a comment - I'm currently implementing the control. It will be ready tomorrow, I think. The idea is to get M22 out by the end of this week-end. Ideally, you'll need to test it as soon as it's in the code (I'll inform you in this JIRA)
        Hide
        Robert Hou added a comment -

        It's great!!!
        Look foward to your reply!
        Thanks Emmanuel!

        Show
        Robert Hou added a comment - It's great!!! Look foward to your reply! Thanks Emmanuel!
        Hide
        Emmanuel Lecharny added a comment -

        The first control (AdDirSync) has been added with http://svn.apache.org/r1587828.

        The AdDirSyncResponseresponse will come later.

        Show
        Emmanuel Lecharny added a comment - The first control (AdDirSync) has been added with http://svn.apache.org/r1587828 . The AdDirSyncResponseresponse will come later.
        Hide
        Robert Hou added a comment -

        Got it, Thanks!

        Show
        Robert Hou added a comment - Got it, Thanks!
        Hide
        Robert Hou added a comment -

        earlier file draft-armijo-ldap-dirsync-00 I supplied has been replaced by draft-armijo-ldap-dirsync-01, accordingly,maxAttributeCount was replaced by maxReturnlength. Just need to update some files.

        Show
        Robert Hou added a comment - earlier file draft-armijo-ldap-dirsync-00 I supplied has been replaced by draft-armijo-ldap-dirsync-01, accordingly,maxAttributeCount was replaced by maxReturnlength. Just need to update some files.
        Hide
        Emmanuel Lecharny added a comment -

        Fixed.

        Show
        Emmanuel Lecharny added a comment - Fixed.
        Hide
        Emmanuel Lecharny added a comment -

        AdDirSyncResponse codec implemented with http://svn.apache.org/r1587971

        I still have to declare the two codecs in the configuration.

        Show
        Emmanuel Lecharny added a comment - AdDirSyncResponse codec implemented with http://svn.apache.org/r1587971 I still have to declare the two codecs in the configuration.
        Hide
        Emmanuel Lecharny added a comment -

        Completed.

        It has to be tested with a AD server, to be sure it works.

        Show
        Emmanuel Lecharny added a comment - Completed. It has to be tested with a AD server, to be sure it works.
        Hide
        Robert Hou added a comment -

        I will tested the codes ASAP. If any result, I will log into this ticket.

        Show
        Robert Hou added a comment - I will tested the codes ASAP. If any result, I will log into this ticket.
        Hide
        Robert Hou added a comment -

        I want to add the two controls into SearchRequest as following:
        -------------
        SearchRequest sr = new SearchRequestImpl();
        AdDirSyncImpl adDirSyncImpl = new AdDirSyncImpl();
        AdDirSyncResponseImpl adDirSyncResponseImpl = new AdDirSyncResponseImpl();
        //Control[] controls = new Control[]

        {adDirSyncImpl,adDirSyncResponseImpl};
        Control[] controls = new Control[]{adDirSyncResponseImpl,adDirSyncImpl};
        sr.addAllControls(controls);
        -------------
        As I test, I find following issues:
        1.SearchRequest only load the last control in the Control array.
        2.If the last control in the Control array is not AdDirSyncResponseImpl, i will get following exception when do the search:
        ----------------------------------
        org.apache.mina.filter.codec.ProtocolEncoderException: java.lang.ClassCastException: org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncImpl cannot be cast to org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncResponse
        ----------------------------------
        3.If the last control in the Control array is AdDirSyncResponseImpl or only set AdDirSyncResponseImpl in the sr.The functionality(I want to monitor spficied attributes) already is archieve. So, looks like AdDirSyncImpl is needless.

        The test code as following:
        @Test
        public void testDirSyncControl()
        {

        LdapConnectionConfig config = new LdapConnectionConfig();
        config.setLdapHost("192.168.80.223");
        config.setLdapPort(50001);
        config.setName("cn=robert,cn=roles,dc=tibco,dc=com");
        config.setCredentials("robert");
        DefaultConfigurableBinaryAttributeDetector bad = new DefaultConfigurableBinaryAttributeDetector();
        config.setBinaryAttributeDetector(bad);
        LdapNetworkConnection connection = new LdapNetworkConnection(config);

        try { connection.bind("cn=robert,cn=roles,dc=tibco,dc=com","robert"); } catch (LdapException e4) { e4.printStackTrace(); }
        SearchRequest sr = new SearchRequestImpl();
        AdDirSyncImpl adDirSyncImpl = new AdDirSyncImpl();
        AdDirSyncResponseImpl adDirSyncResponseImpl = new AdDirSyncResponseImpl();
        // Control[] controls = new Control[]{adDirSyncImpl,adDirSyncResponseImpl}

        ;// is ok
        // Control[] controls = new Control[]

        {adDirSyncResponseImpl,adDirSyncImpl}

        ;// will cause org.apache.mina.filter.codec.ProtocolEncoderException: java.lang.ClassCastException:
        // sr.addAllControls(controls);
        sr.addControl(adDirSyncResponseImpl);//is ok
        try

        { sr.setBase(new Dn("DC=tibco,DC=com")); }

        catch (LdapInvalidDnException e1)

        { e1.printStackTrace(); }
        try { sr.setFilter("(objectClass=inetorgperson)"); } catch (LdapException e1) { e1.printStackTrace(); }

        sr.setScope(SearchScope.SUBTREE);
        SearchCursor cursor = null;
        try

        { cursor = connection.search(sr); }

        catch(LdapException e)

        { e.printStackTrace(); }

        try {
        while(cursor.next()){
        if(!cursor.isDone())

        { continue; }


        }
        } catch (LdapException e4)

        { e4.printStackTrace(); } catch (CursorException e4) { e4.printStackTrace(); }

        byte[] cookie = null;
        if(cursor.isDone()){
        SearchResultDone searchResultDone = cursor.getSearchResultDone();
        Control control = searchResultDone.getControl(AdDirSyncResponseImpl.OID);
        if (control instanceof AdDirSyncResponseDecorator)

        { AdDirSyncResponseDecorator adDirSyncResponseDecorator = (AdDirSyncResponseDecorator)control; cookie = adDirSyncResponseDecorator.getCookie(); }

        }

        String[] returnAttributes =

        {"description"}

        ;
        sr.addAttributes(returnAttributes);
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        while(true){
        try {
        String input;
        while (true) {
        System.out.println("Press x to exit, return to continue");
        input = in.readLine();
        if (input.startsWith("x") || input.startsWith("X"))

        { connection.close(); System.exit(0); }

        else

        { break; }

        }

        }catch (IOException e)

        { System.err.println(); }


        adDirSyncResponseImpl.setCookie(cookie);
        try

        { cursor = connection.search(sr); }

        catch (LdapException e)

        { e.printStackTrace(); }
        int i = 0;
        try {
        while(cursor.next()){
        i++;
        Entry entry = cursor.getEntry();
        Dn dn = entry.getDn();
        System.out.println("dn = " + dn);
        Collection<Attribute> colAttribute = entry.getAttributes();
        Iterator<Attribute> itAttribute = colAttribute.iterator();
        while(itAttribute.hasNext()){
        Attribute attribute = itAttribute.next();
        String attributeName = attribute.getUpId();
        Iterator<Value<?>> itValue = attribute.iterator();
        while(itValue.hasNext()){
        Value<?> value = itValue.next();
        if(value.isHumanReadable()){ String strValue = value.getString(); System.out.println("\t" + attributeName + "=" + strValue); }else{ System.out.println("\t" + attributeName + "withBinary=" + value.getValue().toString()); }

        }
        }
        }
        } catch (LdapException e) { e.printStackTrace(); }

        catch (CursorException e)

        { e.printStackTrace(); }

        System.out.println("total is " + i);
        if(cursor.isDone()){
        SearchResultDone searchResultDone = cursor.getSearchResultDone();
        Control control = searchResultDone.getControl(AdDirSyncResponseImpl.OID);
        if (control instanceof AdDirSyncResponseDecorator)

        { AdDirSyncResponseDecorator adDirSyncResponseDecorator = (AdDirSyncResponseDecorator)control; cookie = adDirSyncResponseDecorator.getCookie(); }

        }
        }

        }

        Show
        Robert Hou added a comment - I want to add the two controls into SearchRequest as following: ------------- SearchRequest sr = new SearchRequestImpl(); AdDirSyncImpl adDirSyncImpl = new AdDirSyncImpl(); AdDirSyncResponseImpl adDirSyncResponseImpl = new AdDirSyncResponseImpl(); //Control[] controls = new Control[] {adDirSyncImpl,adDirSyncResponseImpl}; Control[] controls = new Control[]{adDirSyncResponseImpl,adDirSyncImpl}; sr.addAllControls(controls); ------------- As I test, I find following issues: 1.SearchRequest only load the last control in the Control array. 2.If the last control in the Control array is not AdDirSyncResponseImpl, i will get following exception when do the search: ---------------------------------- org.apache.mina.filter.codec.ProtocolEncoderException: java.lang.ClassCastException: org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncImpl cannot be cast to org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncResponse ---------------------------------- 3.If the last control in the Control array is AdDirSyncResponseImpl or only set AdDirSyncResponseImpl in the sr.The functionality(I want to monitor spficied attributes) already is archieve. So, looks like AdDirSyncImpl is needless. The test code as following: @Test public void testDirSyncControl() { LdapConnectionConfig config = new LdapConnectionConfig(); config.setLdapHost("192.168.80.223"); config.setLdapPort(50001); config.setName("cn=robert,cn=roles,dc=tibco,dc=com"); config.setCredentials("robert"); DefaultConfigurableBinaryAttributeDetector bad = new DefaultConfigurableBinaryAttributeDetector(); config.setBinaryAttributeDetector(bad); LdapNetworkConnection connection = new LdapNetworkConnection(config); try { connection.bind("cn=robert,cn=roles,dc=tibco,dc=com","robert"); } catch (LdapException e4) { e4.printStackTrace(); } SearchRequest sr = new SearchRequestImpl(); AdDirSyncImpl adDirSyncImpl = new AdDirSyncImpl(); AdDirSyncResponseImpl adDirSyncResponseImpl = new AdDirSyncResponseImpl(); // Control[] controls = new Control[]{adDirSyncImpl,adDirSyncResponseImpl} ;// is ok // Control[] controls = new Control[] {adDirSyncResponseImpl,adDirSyncImpl} ;// will cause org.apache.mina.filter.codec.ProtocolEncoderException: java.lang.ClassCastException: // sr.addAllControls(controls); sr.addControl(adDirSyncResponseImpl);//is ok try { sr.setBase(new Dn("DC=tibco,DC=com")); } catch (LdapInvalidDnException e1) { e1.printStackTrace(); } try { sr.setFilter("(objectClass=inetorgperson)"); } catch (LdapException e1) { e1.printStackTrace(); } sr.setScope(SearchScope.SUBTREE); SearchCursor cursor = null; try { cursor = connection.search(sr); } catch(LdapException e) { e.printStackTrace(); } try { while(cursor.next()){ if(!cursor.isDone()) { continue; } } } catch (LdapException e4) { e4.printStackTrace(); } catch (CursorException e4) { e4.printStackTrace(); } byte[] cookie = null; if(cursor.isDone()){ SearchResultDone searchResultDone = cursor.getSearchResultDone(); Control control = searchResultDone.getControl(AdDirSyncResponseImpl.OID); if (control instanceof AdDirSyncResponseDecorator) { AdDirSyncResponseDecorator adDirSyncResponseDecorator = (AdDirSyncResponseDecorator)control; cookie = adDirSyncResponseDecorator.getCookie(); } } String[] returnAttributes = {"description"} ; sr.addAttributes(returnAttributes); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); while(true){ try { String input; while (true) { System.out.println("Press x to exit, return to continue"); input = in.readLine(); if (input.startsWith("x") || input.startsWith("X")) { connection.close(); System.exit(0); } else { break; } } }catch (IOException e) { System.err.println(); } adDirSyncResponseImpl.setCookie(cookie); try { cursor = connection.search(sr); } catch (LdapException e) { e.printStackTrace(); } int i = 0; try { while(cursor.next()){ i++; Entry entry = cursor.getEntry(); Dn dn = entry.getDn(); System.out.println("dn = " + dn); Collection<Attribute> colAttribute = entry.getAttributes(); Iterator<Attribute> itAttribute = colAttribute.iterator(); while(itAttribute.hasNext()){ Attribute attribute = itAttribute.next(); String attributeName = attribute.getUpId(); Iterator<Value<?>> itValue = attribute.iterator(); while(itValue.hasNext()){ Value<?> value = itValue.next(); if(value.isHumanReadable()){ String strValue = value.getString(); System.out.println("\t" + attributeName + "=" + strValue); }else{ System.out.println("\t" + attributeName + "withBinary=" + value.getValue().toString()); } } } } } catch (LdapException e) { e.printStackTrace(); } catch (CursorException e) { e.printStackTrace(); } System.out.println("total is " + i); if(cursor.isDone()){ SearchResultDone searchResultDone = cursor.getSearchResultDone(); Control control = searchResultDone.getControl(AdDirSyncResponseImpl.OID); if (control instanceof AdDirSyncResponseDecorator) { AdDirSyncResponseDecorator adDirSyncResponseDecorator = (AdDirSyncResponseDecorator)control; cookie = adDirSyncResponseDecorator.getCookie(); } } } }
        Hide
        Emmanuel Lecharny added a comment -

        You should only add the AdDirSync control, not the response. The response will be returned by the SearchResultDone.

        I think that the client tries to associate the response to the AdDirSync control, because they have the same OID. I have to check that. In any case, this is a bug. I'll fix it.

        Show
        Emmanuel Lecharny added a comment - You should only add the AdDirSync control, not the response. The response will be returned by the SearchResultDone. I think that the client tries to associate the response to the AdDirSync control, because they have the same OID. I have to check that. In any case, this is a bug. I'll fix it.
        Hide
        Robert Hou added a comment -

        If I only add the AdDirSync control. I will get following exception when do the search:
        ----------------------------------
        org.apache.mina.filter.codec.ProtocolEncoderException: java.lang.ClassCastException: org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncImpl cannot be cast to org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncResponse
        ----------------------------------

        Show
        Robert Hou added a comment - If I only add the AdDirSync control. I will get following exception when do the search: ---------------------------------- org.apache.mina.filter.codec.ProtocolEncoderException: java.lang.ClassCastException: org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncImpl cannot be cast to org.apache.directory.api.ldap.extras.controls.ad.AdDirSyncResponse ----------------------------------
        Hide
        Emmanuel Lecharny added a comment -

        Ok, I see what's going wrong. The controlFactories Map (which associates an OID to a control) can't contain both controls with the same OID. The factory should refer to both controls.

        Show
        Emmanuel Lecharny added a comment - Ok, I see what's going wrong. The controlFactories Map (which associates an OID to a control) can't contain both controls with the same OID. The factory should refer to both controls.
        Hide
        Emmanuel Lecharny added a comment -

        The problem is that the API is supposed to be used both side (client and server). How should we know which side we are on ?
        If we are on the client side, we should have a factory that encode the AdDirSync control and decode the AdDirSyncResponse control
        If we are on the server side, this is the opposite...

        OTOH, there is no reason for using the server side control, ever... ADS will never implement the Ad DIRSYNC protocol...

        Show
        Emmanuel Lecharny added a comment - The problem is that the API is supposed to be used both side (client and server). How should we know which side we are on ? If we are on the client side, we should have a factory that encode the AdDirSync control and decode the AdDirSyncResponse control If we are on the server side, this is the opposite... OTOH, there is no reason for using the server side control, ever... ADS will never implement the Ad DIRSYNC protocol...
        Hide
        Robert Hou added a comment -

        Only set AdDirSyncImpl control in the SearchRequest is right.
        Looks like Apache API has some issues to handle request control and response control when they have same OID. Even though I don't know how should API know which side it is on, as far as I know JNDI has the correct implementation for this from the test. Please refer to following codes:

        import java.io.*;
        import java.util.Hashtable;

        import javax.naming.*;
        import javax.naming.ldap.*;
        import javax.naming.directory.*;

        import com.sun.jndi.ldap.ctl.*;

        public class ModChanges4SpecifiedFields {
        public static void main(String[] args) {
        Hashtable env = new Hashtable();
        String adminName = "cn=robert,cn=roles,dc=tibco,dc=com";
        String adminPassword = "robert";
        String ldapURL = "ldap://192.168.80.223:50001";
        env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
        // set security credentials, note using simple cleartext authentication
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, adminName);
        env.put(Context.SECURITY_CREDENTIALS, adminPassword);

        // connect to my domain controller
        env.put(Context.PROVIDER_URL, ldapURL);

        try {
        // Create the initial directory context
        LdapContext ctx = new InitialLdapContext(env, null);
        // Create the search controls
        SearchControls searchCtls = new SearchControls();
        // Specify the attributes to return, null initially return all
        // values
        // and in subsequent calls, null returns all modified attributes
        String returnedAtts[] = {};
        searchCtls.setReturningAttributes(returnedAtts);
        // Specify the search scope
        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        // specify the LDAP search filter
        String searchFilter = "(&(objectClass=user))";
        // Specify the Base for the search
        String searchBase = "DC=tibco,DC=com";
        // initialize counter to total the results
        int totalResults = 0;
        // Specify the DirSync and DirSyncResponse controls
        byte[] cookie = null;
        Control[] rspCtls;
        Control[] ctls = new Control[]

        { new DirSyncControl() }

        ;
        ctx.setRequestControls(ctls);
        // Search for objects using the filter
        NamingEnumeration answer = ctx.search(searchBase, searchFilter,searchCtls);
        // Loop through the search results
        while (answer.hasMoreElements())

        { SearchResult sr = (SearchResult) answer.next(); totalResults++; System.out.println(">>>" + sr.getName()); // First time around, no need to print any attributes }

        System.out.println("Current results: " + totalResults);

        // save the response controls
        if ((rspCtls = ctx.getResponseControls()) != null) {
        System.out.println("Response Controls: " + rspCtls.length);
        for (int i = 0; i < rspCtls.length; i++) {
        if (rspCtls[i] instanceof DirSyncResponseControl1)

        { DirSyncResponseControl1 rspCtl = (DirSyncResponseControl1) rspCtls[i]; cookie = rspCtl.getCookie(); System.out.println("Flag: " + rspCtl.getFlag()); System.out.println("Length: "+ rspCtl.getMaxReturnLength()); System.out.println("Cookie: " + cookie.toString()); }

        }

        }
        // Now start a loop, prompt the user to continue/quit and continue
        // searching for modified objects

        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

        while (true) {
        try {
        String input;
        while (true) {
        System.out.println("Press x to exit, return to continue");
        input = in.readLine();
        if (input.startsWith("x") || input.startsWith("X"))

        { ctx.close(); System.exit(0); }

        else

        { break; }

        }

        }

        catch (IOException e)

        { System.err.println(); }

        // now lets do the search again using the cookie
        totalResults = 0;
        // use the saved cookie in the DirSync control
        ctx.setRequestControls(new Control[]

        { new DirSyncControl1(1,Integer.MAX_VALUE, cookie, true) }

        );
        // execute the search again
        String returnedAtts1[] =

        {"description"}

        ;
        searchCtls.setReturningAttributes(returnedAtts1);
        answer = ctx.search(searchBase, searchFilter, searchCtls);
        // Loop through the search results
        while (answer.hasMoreElements()) {
        SearchResult sr = (SearchResult) answer.next();
        totalResults++;
        System.out.println(">>>" + sr.getName());
        // Print out the modified attributes
        // instanceType and objectGUID are always returned
        Attributes attrs = sr.getAttributes();
        if (attrs != null) {
        try {
        for (NamingEnumeration ae = attrs.getAll(); ae.hasMore()

        { Attribute attr = (Attribute) ae.next(); System.out.println("Attribute: " + attr.getID()); for (NamingEnumeration e = attr.getAll(); e.hasMore(); System.out.println(" "+ e.next().toString())); }

        }
        catch (NullPointerException e)

        { System.err.println(); }

        }

        }
        System.out.println("Recently Modified: " + totalResults);
        // Save the response control again
        if ((rspCtls = ctx.getResponseControls()) != null) {
        System.out.println("Response Controls: " + rspCtls.length);
        for (int i = 0; i < rspCtls.length; i++) {
        if (rspCtls[i] instanceof DirSyncResponseControl1)

        { DirSyncResponseControl1 rspCtl = (DirSyncResponseControl1) rspCtls[i]; cookie = rspCtl.getCookie(); System.out.println("Flag: " + rspCtl.getFlag()); System.out.println("Length: "+ rspCtl.getMaxReturnLength()); System.out.println("Cookie: " + cookie.toString()); }

        }

        }

        }

        }

        catch (NamingException e)

        { System.err.println("Problem searching directory: " + e); }

        catch (java.io.IOException e)

        { System.err.println("Problem searching directory: " + e); }

        }

        }

        Show
        Robert Hou added a comment - Only set AdDirSyncImpl control in the SearchRequest is right. Looks like Apache API has some issues to handle request control and response control when they have same OID. Even though I don't know how should API know which side it is on, as far as I know JNDI has the correct implementation for this from the test. Please refer to following codes: import java.io.*; import java.util.Hashtable; import javax.naming.*; import javax.naming.ldap.*; import javax.naming.directory.*; import com.sun.jndi.ldap.ctl.*; public class ModChanges4SpecifiedFields { public static void main(String[] args) { Hashtable env = new Hashtable(); String adminName = "cn=robert,cn=roles,dc=tibco,dc=com"; String adminPassword = "robert"; String ldapURL = "ldap://192.168.80.223:50001"; env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); // set security credentials, note using simple cleartext authentication env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, adminName); env.put(Context.SECURITY_CREDENTIALS, adminPassword); // connect to my domain controller env.put(Context.PROVIDER_URL, ldapURL); try { // Create the initial directory context LdapContext ctx = new InitialLdapContext(env, null); // Create the search controls SearchControls searchCtls = new SearchControls(); // Specify the attributes to return, null initially return all // values // and in subsequent calls, null returns all modified attributes String returnedAtts[] = {}; searchCtls.setReturningAttributes(returnedAtts); // Specify the search scope searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE); // specify the LDAP search filter String searchFilter = "(&(objectClass=user))"; // Specify the Base for the search String searchBase = "DC=tibco,DC=com"; // initialize counter to total the results int totalResults = 0; // Specify the DirSync and DirSyncResponse controls byte[] cookie = null; Control[] rspCtls; Control[] ctls = new Control[] { new DirSyncControl() } ; ctx.setRequestControls(ctls); // Search for objects using the filter NamingEnumeration answer = ctx.search(searchBase, searchFilter,searchCtls); // Loop through the search results while (answer.hasMoreElements()) { SearchResult sr = (SearchResult) answer.next(); totalResults++; System.out.println(">>>" + sr.getName()); // First time around, no need to print any attributes } System.out.println("Current results: " + totalResults); // save the response controls if ((rspCtls = ctx.getResponseControls()) != null) { System.out.println("Response Controls: " + rspCtls.length); for (int i = 0; i < rspCtls.length; i++) { if (rspCtls [i] instanceof DirSyncResponseControl1) { DirSyncResponseControl1 rspCtl = (DirSyncResponseControl1) rspCtls[i]; cookie = rspCtl.getCookie(); System.out.println("Flag: " + rspCtl.getFlag()); System.out.println("Length: "+ rspCtl.getMaxReturnLength()); System.out.println("Cookie: " + cookie.toString()); } } } // Now start a loop, prompt the user to continue/quit and continue // searching for modified objects BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); while (true) { try { String input; while (true) { System.out.println("Press x to exit, return to continue"); input = in.readLine(); if (input.startsWith("x") || input.startsWith("X")) { ctx.close(); System.exit(0); } else { break; } } } catch (IOException e) { System.err.println(); } // now lets do the search again using the cookie totalResults = 0; // use the saved cookie in the DirSync control ctx.setRequestControls(new Control[] { new DirSyncControl1(1,Integer.MAX_VALUE, cookie, true) } ); // execute the search again String returnedAtts1[] = {"description"} ; searchCtls.setReturningAttributes(returnedAtts1); answer = ctx.search(searchBase, searchFilter, searchCtls); // Loop through the search results while (answer.hasMoreElements()) { SearchResult sr = (SearchResult) answer.next(); totalResults++; System.out.println(">>>" + sr.getName()); // Print out the modified attributes // instanceType and objectGUID are always returned Attributes attrs = sr.getAttributes(); if (attrs != null) { try { for (NamingEnumeration ae = attrs.getAll(); ae.hasMore() { Attribute attr = (Attribute) ae.next(); System.out.println("Attribute: " + attr.getID()); for (NamingEnumeration e = attr.getAll(); e.hasMore(); System.out.println(" "+ e.next().toString())); } } catch (NullPointerException e) { System.err.println(); } } } System.out.println("Recently Modified: " + totalResults); // Save the response control again if ((rspCtls = ctx.getResponseControls()) != null) { System.out.println("Response Controls: " + rspCtls.length); for (int i = 0; i < rspCtls.length; i++) { if (rspCtls [i] instanceof DirSyncResponseControl1) { DirSyncResponseControl1 rspCtl = (DirSyncResponseControl1) rspCtls[i]; cookie = rspCtl.getCookie(); System.out.println("Flag: " + rspCtl.getFlag()); System.out.println("Length: "+ rspCtl.getMaxReturnLength()); System.out.println("Cookie: " + cookie.toString()); } } } } } catch (NamingException e) { System.err.println("Problem searching directory: " + e); } catch (java.io.IOException e) { System.err.println("Problem searching directory: " + e); } } }
        Hide
        Emmanuel Lecharny added a comment -

        I have merged both controls in one. When we encode (ie, the client is sending the control), we use the AdDirSync code. When we decode (ie when the client receives the response), we use teh AdDirSyncResponse code.

        We will have only one factory. That should work. Code will be ready in a matter of minutes for tests.

        Show
        Emmanuel Lecharny added a comment - I have merged both controls in one. When we encode (ie, the client is sending the control), we use the AdDirSync code. When we decode (ie when the client receives the response), we use teh AdDirSyncResponse code. We will have only one factory. That should work. Code will be ready in a matter of minutes for tests.
        Hide
        Emmanuel Lecharny added a comment -

        Committed in http://svn.apache.org/r1588204

        Can you svn up and give it a try ? (The AdDirSyncResponse control does not exist anymore)

        Show
        Emmanuel Lecharny added a comment - Committed in http://svn.apache.org/r1588204 Can you svn up and give it a try ? (The AdDirSyncResponse control does not exist anymore)
        Hide
        Robert Hou added a comment -

        Ok, I will test it tomorrow. I need to resetting my configuration for Maven and then compile the latest source. Today our colleague help me compile the source. And I am newer to Maven complie.

        Show
        Robert Hou added a comment - Ok, I will test it tomorrow. I need to resetting my configuration for Maven and then compile the latest source. Today our colleague help me compile the source. And I am newer to Maven complie.
        Hide
        Robert Hou added a comment -

        It is fine for the latest soure.
        Thanks Emmanuel!

        Show
        Robert Hou added a comment - It is fine for the latest soure. Thanks Emmanuel!
        Hide
        Emmanuel Lecharny added a comment -

        Great ! I'm going to cut a release this afternoon.

        Show
        Emmanuel Lecharny added a comment - Great ! I'm going to cut a release this afternoon.
        Hide
        Robert Hou added a comment -

        OK, Thanks Emmanuel!

        Show
        Robert Hou added a comment - OK, Thanks Emmanuel!

          People

          • Assignee:
            Unassigned
            Reporter:
            Robert Hou
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development