// Path: src/main/java/net/tirasa/adsddl/ntsd/controls/DirSyncControl.java
// public class DirSyncControl extends BasicControl {
// 
//     private static final long serialVersionUID = -930993758829518418L;
// 
//     /**
//      * LDAP_SERVER_DIRSYNC_OID.
//      * Directory synchronization control.
//      */
//     public static final String OID = "1.2.840.113556.1.4.841";
// 
//     /**
//      * Empty cookie.
//      */
//     private static final byte[] EMPTY_COOKIE = new byte[0];
// 
//     /**
//      * LDAP_DIRSYNC_INCREMENTAL_VALUES | LDAP_DIRSYNC_ANCESTORS_FIRST_ORDER | LDAP_DIRSYNC_OBJECT_SECURITY
//      * LDAP_DIRSYNC_OBJECT_SECURITY: 0x00000001
//      * LDAP_DIRSYNC_ANCESTORS_FIRST_ORDER: 0x00000800
//      * LDAP_DIRSYNC_PUBLIC_DATA_ONLY: 0x00002000
//      * LDAP_DIRSYNC_INCREMENTAL_VALUES: 0x80000000
//      */
//     private int flags = 0x80000801;
// 
//     private final byte[] cookie;
// 
//     /**
//      * Constructor.
//      * Specify an empty cookie.
//      */
//     public DirSyncControl() {
//         super(OID, true, null);
//         this.cookie = EMPTY_COOKIE;
//         super.value = berEncodedValue();
//     }
// 
//     /**
//      * Constructor.
//      *
//      * @param cookie cookie.
//      */
//     public DirSyncControl(byte[] cookie) {
//         super(OID, true, cookie);
//         this.cookie = cookie;
//         super.value = berEncodedValue();
//     }
// 
//     /**
//      * BER encode the cookie value.
//      *
//      * @param cookie cookie value to be encoded.
//      * @return ber encoded cookie value.
//      */
//     private byte[] berEncodedValue() {
//         final byte[] cookieSize = NumberFacility.leftTrim(NumberFacility.getBytes(cookie.length));
//         final byte[] size = NumberFacility.leftTrim(NumberFacility.getBytes(14 + cookieSize.length + cookie.length));
// 
//         final ByteBuffer buff = ByteBuffer.allocate(1 + 1 + size.length + 14 + cookieSize.length + cookie.length);
// 
//         buff.put((byte) 0x30); // (Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
//         buff.put((byte) (size.length == 1 ? 0x81 : size.length == 2 ? 0x82 : 0x83)); // size type (short or long form)
//         buff.put(size); // sequence size
//         buff.put((byte) 0x02); // 4bytes int tag
//         buff.put((byte) 0x04); // int size
//         buff.putInt(flags); // flags
//         buff.put((byte) 0x02); // 4bytes int tag
//         buff.put((byte) 0x04); // int size
//         buff.putInt(Integer.MAX_VALUE); // max attribute count
//         buff.put((byte) 0x04); // byte array tag
//         buff.put((byte) (cookieSize.length == 1 ? 0x81 : cookieSize.length == 2 ? 0x82 : 0x83)); // short or long form
//         buff.put(cookieSize); // byte array size
//         if (cookie.length > 0) {
//             buff.put(cookie); // (cookie, Ber.ASN_OCTET_STR);
//         }
//         return buff.array();
//     }
// 
//     public DirSyncControl setFlags(final int flags) {
//         this.flags = flags;
//         // value encoding must be regenerated to provide new flags ...
//         super.value = berEncodedValue();
//         return this;
//     }
// }


import static org.junit.Assert.assertEquals;
import com.sun.jndi.ldap.ctl.DirSyncResponseControl;
import java.util.AbstractMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.LdapContext;
import net.tirasa.adsddl.ntsd.controls.DirSyncControl;
import org.junit.Test;
/*
 * Copyright (C) 2018 Tirasa (info@tirasa.net)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.tirasa.adsddl.it;




public class DirSyncTest extends AbstractTest {

    private static final long serialVersionUID = 1L;

    @Test
    public void syncUser() throws Exception {
        // -----------------------------------
        // Create search control
        // -----------------------------------
        final SearchControls searchCtls = createDefaultSearchControls();
        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        searchCtls.setReturningAttributes(null);
        searchCtls.setTimeLimit(20000);
        // -----------------------------------

        // retrieve latest sync token
// Path: src/main/java/net/tirasa/adsddl/ntsd/controls/DirSyncControl.java
// public class DirSyncControl extends BasicControl {
// 
//     private static final long serialVersionUID = -930993758829518418L;
// 
//     /**
//      * LDAP_SERVER_DIRSYNC_OID.
//      * Directory synchronization control.
//      */
//     public static final String OID = "1.2.840.113556.1.4.841";
// 
//     /**
//      * Empty cookie.
//      */
//     private static final byte[] EMPTY_COOKIE = new byte[0];
// 
//     /**
//      * LDAP_DIRSYNC_INCREMENTAL_VALUES | LDAP_DIRSYNC_ANCESTORS_FIRST_ORDER | LDAP_DIRSYNC_OBJECT_SECURITY
//      * LDAP_DIRSYNC_OBJECT_SECURITY: 0x00000001
//      * LDAP_DIRSYNC_ANCESTORS_FIRST_ORDER: 0x00000800
//      * LDAP_DIRSYNC_PUBLIC_DATA_ONLY: 0x00002000
//      * LDAP_DIRSYNC_INCREMENTAL_VALUES: 0x80000000
//      */
//     private int flags = 0x80000801;
// 
//     private final byte[] cookie;
// 
//     /**
//      * Constructor.
//      * Specify an empty cookie.
//      */
//     public DirSyncControl() {
//         super(OID, true, null);
//         this.cookie = EMPTY_COOKIE;
//         super.value = berEncodedValue();
//     }
// 
//     /**
//      * Constructor.
//      *
//      * @param cookie cookie.
//      */
//     public DirSyncControl(byte[] cookie) {
//         super(OID, true, cookie);
//         this.cookie = cookie;
//         super.value = berEncodedValue();
//     }
// 
//     /**
//      * BER encode the cookie value.
//      *
//      * @param cookie cookie value to be encoded.
//      * @return ber encoded cookie value.
//      */
//     private byte[] berEncodedValue() {
//         final byte[] cookieSize = NumberFacility.leftTrim(NumberFacility.getBytes(cookie.length));
//         final byte[] size = NumberFacility.leftTrim(NumberFacility.getBytes(14 + cookieSize.length + cookie.length));
// 
//         final ByteBuffer buff = ByteBuffer.allocate(1 + 1 + size.length + 14 + cookieSize.length + cookie.length);
// 
//         buff.put((byte) 0x30); // (Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
//         buff.put((byte) (size.length == 1 ? 0x81 : size.length == 2 ? 0x82 : 0x83)); // size type (short or long form)
//         buff.put(size); // sequence size
//         buff.put((byte) 0x02); // 4bytes int tag
//         buff.put((byte) 0x04); // int size
//         buff.putInt(flags); // flags
//         buff.put((byte) 0x02); // 4bytes int tag
//         buff.put((byte) 0x04); // int size
//         buff.putInt(Integer.MAX_VALUE); // max attribute count
//         buff.put((byte) 0x04); // byte array tag
//         buff.put((byte) (cookieSize.length == 1 ? 0x81 : cookieSize.length == 2 ? 0x82 : 0x83)); // short or long form
//         buff.put(cookieSize); // byte array size
//         if (cookie.length > 0) {
//             buff.put(cookie); // (cookie, Ber.ASN_OCTET_STR);
//         }
//         return buff.array();
//     }
// 
//     public DirSyncControl setFlags(final int flags) {
//         this.flags = flags;
//         // value encoding must be regenerated to provide new flags ...
//         super.value = berEncodedValue();
//         return this;
//     }
// }


// Path: src/test/java/net/tirasa/adsddl/it/DirSyncTest.java
import static org.junit.Assert.assertEquals;
import com.sun.jndi.ldap.ctl.DirSyncResponseControl;
import java.util.AbstractMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.LdapContext;
import net.tirasa.adsddl.ntsd.controls.DirSyncControl;
import org.junit.Test;

/*
 * Copyright (C) 2018 Tirasa (info@tirasa.net)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.tirasa.adsddl.it;




public class DirSyncTest extends AbstractTest {

    private static final long serialVersionUID = 1L;

    @Test
    public void syncUser() throws Exception {
        // -----------------------------------
        // Create search control
        // -----------------------------------
        final SearchControls searchCtls = createDefaultSearchControls();
        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        searchCtls.setReturningAttributes(null);
        searchCtls.setTimeLimit(20000);
        // -----------------------------------

        // retrieve latest sync token
        ctx.setRequestControls(new Control[] { new DirSyncControl().setFlags(0x00000801) });