Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
==================== DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved. Copyright 2011-2013 Tirasa. All rights reserved. The contents of this file are subject to the terms of the Common Development and Distribution License("CDDL") (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the License at https://oss.oracle.com/licenses/CDDL See the License for the specific language governing permissions and limitations under the License. When distributing the Covered Code, include this CDDL Header Notice in each file and include the License file at https://oss.oracle.com/licenses/CDDL. If applicable, add the following below this CDDL Header, with the fields enclosed by brackets [] replaced by your own identifying information: "Portions Copyrighted [year] [name of copyright owner]" ====================
 
 package org.connid.bundles.ad.sync;
 
 import java.util.Set;
An implementation of the sync operation based on the DirSync protocol, for Active Directory.
 
 public class ADSyncStrategy {
 
     private static final Log LOG = Log.getLog(ADSyncStrategy.class);
 
     private final transient ADConnection conn;
 
     private transient SyncToken latestSyncToken;
 
     private final ADUtilities utils;
 
     public ADSyncStrategy(final ADConnection conn) {
         this. = conn;
         this. = new ADUtilities(conn);
     }
 
     private Set<SearchResultsearch(
             final LdapContext ctx,
             final String filter,
             final SearchControls searchCtls,
             final boolean updateLastSyncToken) {
 
         final Set<SearchResultresult = new HashSet<SearchResult>();
 
         for (String baseContextDn : .getConfiguration().getBaseContextsToSynchronize()) {
 
             if (.isOk()) {
                 .ok("Searching from " + baseContextDn);
             }
 
             try {
                 final NamingEnumeration<SearchResultanswer = ctx.search(baseContextDnfiltersearchCtls);
 
                 while (answer.hasMoreElements()) {
                     result.add(answer.nextElement());
                 }
 
                 if (updateLastSyncToken) {
                     final Control[] rspCtls = ctx.getResponseControls();
 
                     if (rspCtls != null) {
                        if (.isOk()) {
                            .ok("Response Controls: {0}"rspCtls.length);
                        }
                        for (int i = 0; i < rspCtls.lengthi++) {
                            if (rspCtls[iinstanceof DirSyncResponseControl) {
                                DirSyncResponseControl dirSyncRspCtl = (DirSyncResponseControlrspCtls[i];
                                 = new SyncToken(dirSyncRspCtl.getCookie());
                            }
                        }
                        if (.isOk()) {
                            .ok("Latest sync token set to {0}");
                        }
                    }
                }
            } catch (NamingException e) {
                .error(e"While searching base context {0} with filter {1} and search controls {2}",
                        baseContextDnfilter.toString(), searchCtls);
            }
        }
        return result;
    }
    public void sync(
            final SyncToken token,
            final SyncResultsHandler handler,
            final OperationOptions options,
            final ObjectClass oclass) {
        // -----------------------------------
        // Create search control
        // -----------------------------------
        final SearchControls searchCtls = LdapInternalSearch.createDefaultSearchControls();
        searchCtls.setSearchScope(.);
        searchCtls.setReturningAttributes(null);
        // -----------------------------------
        // -----------------------------------
        // Get Synchronization Context
        // -----------------------------------
        final LdapContext ctx;
        try {
            if (token == null
                    || token.getValue() == null
                    || !(token.getValue() instanceof byte[])
                    || ((byte[]) token.getValue()).length == 0) {
                if (.isOk()) {
                    .ok("Synchronization with empty token.");
                }
                ctx = .getSyncContext(new Control[]{new DirSyncControl()});
                if (((ADConfiguration.getConfiguration()).isStartSyncFromToday()) {
                    search(ctx"(cn=__CONNID-NORES__)"searchCtlstrue);
                    return;
                }
            } else {
                if (.isOk()) {
                    .ok("Synchronization with token.");
                }
                ctx = .getSyncContext(new Control[]{new DirSyncControl((byte[]) token.getValue())});
            }
        } catch (Exception e) {
            throw new ConnectorException("Could not set DirSync request controls"e);
        }
        // -----------------------------------
        // -----------------------------------
        // Create search filter
        // -----------------------------------
        final String filter = oclass == .
                ? // get user filter
                DirSyncUtils.createDirSyncUFilter((ADConfiguration.getConfiguration())
                : // get group filter
                DirSyncUtils.createDirSyncGFilter((ADConfiguration.getConfiguration());
        if (.isOk()) {
            .ok("Search filter: " + filter);
        }
        // -----------------------------------
        final String[] attrsToGetOption = options.getAttributesToGet();
        final Set<StringattrsToGet = .getAttributesToGet(attrsToGetOptionoclass);
        final Set<SearchResultchanges = search(ctxfiltersearchCtlstrue);
        if (oclass.is(.)) {
            for (SearchResult sr : changes) {
                try {
                    handleSyncUDelta(ctxsrattrsToGethandler);
                } catch (NamingException e) {
                    .error(e"SyncDelta handling for '{0}' failed"sr.getName());
                }
            }
        } else {
            for (SearchResult sr : changes) {
                try {
                    handleSyncGDelta(ctxsrattrsToGethandler);
                } catch (NamingException e) {
                    .error(e"SyncDelta handling for '{0}' failed"sr.getName());
                }
            }
        }
    }
    public SyncToken getLatestSyncToken() {
        return ;
    }
    @SuppressWarnings("unchecked")
    private void handleSyncUDelta(
            final LdapContext ctx,
            final SearchResult result,
            final Collection<StringattrsToGet,
            final SyncResultsHandler handler)
            throws NamingException {
        if (ctx == null || result == null) {
            throw new ConnectorException("Invalid context or search result.");
        }
        ctx.setRequestControls(new Control[]{new DeletedControl()});
        // Just used to retrieve object classes and to pass to getSyncDelta
        Attributes profile = result.getAttributes();
        if (.isOk()) {
            .ok("Object profile: {0}"profile);
        }
        String guid = DirSyncUtils.getGuidAsString((byte[]) profile.get("objectGUID").get());
        boolean isDeleted = false;
        try {
            javax.naming.directory.Attribute attributeIsDeleted = profile.get("isDeleted");
            isDeleted =
                    attributeIsDeleted != null
                    && attributeIsDeleted.get() != null
                    && Boolean.parseBoolean(
                    attributeIsDeleted.get().toString());
        } catch (NoSuchElementException e) {
            if (.isOk()) {
                .ok("Cannot find the isDeleted element for user.");
            }
        } catch (Throwable t) {
            .error(t"Error retrieving isDeleted attribute");
        }
        // We need for this beacause DirSync can return an uncomplete profile.
        profile = ctx.getAttributes("<GUID=" + guid + ">");
        final Attribute objectClasses = profile.get("objectClass");
        final ADConfiguration conf = (ADConfiguration.getConfiguration();
        final javax.naming.directory.Attribute member11;
        final javax.naming.directory.Attribute member00;
        if (objectClasses.contains("group")) {
            // search for users in adn users out
            if (.isOk()) {
                .ok("Modified group {0}"result.getNameInNamespace());
            }
            member11 = result.getAttributes().get("member;range=1-1");
            member00 = result.getAttributes().get("member;range=0-0");
            ctx.setRequestControls(null);
            if (member11 != null && !conf.isLoading()) {
                if (.isOk()) {
                    .ok("Found users 'IN' ...");
                }
                handleInOutEntries(
                        ctx,
                        .,
                        (NamingEnumeration<String>) member11.getAll(),
                        DirSyncUtils.getUserFilter(conf),
                        handler,
                        conf,
                        attrsToGet);
            }
            if (member00 != null && conf.isRetrieveDeletedUser()) {
                // users to be removed
                if (.isOk()) {
                    .ok("Found users 'OUT' ...");
                }
                handleInOutEntries(
                        ctx,
                        .,
                        (NamingEnumeration<String>) member00.getAll(),
                        DirSyncUtils.getUserFilter(conf),
                        handler,
                        conf,
                        attrsToGet);
            }
        } else if (objectClasses.contains("user")) {
            if (.isOk()) {
                .ok("Created/Updated/Deleted user {0}",
                        result.getNameInNamespace());
            }
            if (isDeleted) {
                if (.isOk()) {
                    .ok("Deleted user {0}"result.getNameInNamespace());
                }
                if (conf.isRetrieveDeletedUser()) {
                    handler.handle(getSyncDelta(
                            .,
                            result.getNameInNamespace(),
                            .,
                            profile,
                            attrsToGet));
                }
            } else {
                // user to be created/updated
                if (.isOk()) {
                    .ok("Created/Updated user {0}"result.getNameInNamespace());
                }
                handleEntry(
                        ctx,
                        .,
                        result.getNameInNamespace(),
                        DirSyncUtils.getUserFilter(conf),
                        handler,
                        conf,
                        attrsToGet);
            }
        } else {
            if (.isInfo()) {
                .info("Invalid object type {0}"objectClasses);
            }
        }
    }
    private void handleSyncGDelta(
            final LdapContext ctx,
            final SearchResult sr,
            final Collection<StringattrsToGet,
            final SyncResultsHandler handler)
            throws NamingException {
        if (ctx == null || sr == null) {
            throw new ConnectorException("Invalid context or search result.");
        }
        ctx.setRequestControls(new Control[]{new DeletedControl()});
        // Just used to retrieve object classes and to pass to getSyncDelta
        Attributes profile = sr.getAttributes();
        if (.isOk()) {
            .ok("Object profile: {0}"profile);
        }
        String guid = DirSyncUtils.getGuidAsString((byte[]) profile.get("objectGUID").get());
        boolean isDeleted = false;
        try {
            javax.naming.directory.Attribute attributeIsDeleted = profile.get("isDeleted");
            isDeleted =
                    attributeIsDeleted != null
                    && attributeIsDeleted.get() != null
                    && Boolean.parseBoolean(
                    attributeIsDeleted.get().toString());
        } catch (NoSuchElementException e) {
            if (.isOk()) {
                .ok("Cannot find the isDeleted element for group.");
            }
        } catch (Throwable t) {
            .error(t"Error retrieving isDeleted attribute");
        }
        // We need for this beacause DirSync can return an uncomplete profile.
        profile = ctx.getAttributes("<GUID=" + guid + ">");
        final Attribute objectClasses = profile.get("objectClass");
        if (objectClasses.contains("group")) {
            final ADConfiguration conf = (ADConfiguration.getConfiguration();
            if (.isOk()) {
                .ok("Created/Updated/Deleted group {0}"sr.getNameInNamespace());
            }
            if (isDeleted) {
                if (.isOk()) {
                    .ok("Deleted group {0}"sr.getNameInNamespace());
                }
                if (conf.isRetrieveDeletedGroup()) {
                    handler.handle(getSyncDelta(
                            .,
                            sr.getNameInNamespace(),
                            .,
                            profile,
                            attrsToGet));
                }
            } else {
                // user to be created/updated
                if (.isOk()) {
                    .ok("Created/Updated group {0}"sr.getNameInNamespace());
                }
                String userDN = sr.getNameInNamespace();
                handleEntry(ctx.userDNconf.getGroupSearchFilter(), handlerconfattrsToGet);
                final javax.naming.directory.Attribute member11 = sr.getAttributes().get("member;range=1-1");
                final javax.naming.directory.Attribute member00 = sr.getAttributes().get("member;range=0-0");
                ctx.setRequestControls(null);
                if (member11 != null && !conf.isLoading()) {
                    if (.isOk()) {
                        .ok("Found entry 'IN' ...");
                    }
                    handleInOutEntries(
                            ctx,
                            .,
                            (NamingEnumeration<String>) member11.getAll(),
                            "(&(objectclass=group)" + conf.getGroupSearchFilter() + ")",
                            handler,
                            conf,
                            attrsToGet);
                }
                if (member00 != null && !conf.isLoading()) {
                    // users to be removed
                    if (.isOk()) {
                        .ok("Found entry 'OUT' ...");
                    }
                    handleInOutEntries(
                            ctx,
                            .,
                            (NamingEnumeration<String>) member00.getAll(),
                            "(&(objectclass=group)" + conf.getGroupSearchFilter() + ")",
                            handler,
                            conf,
                            attrsToGet);
                }
            }
        } else {
            if (.isInfo()) {
                .info("Invalid object type {0}"objectClasses);
            }
        }
    }
    private SyncDelta getSyncDelta(
            final ObjectClass oclass,
            final String entryDN,
            final SyncDeltaType syncDeltaType,
            final Attributes profile,
            final Collection<StringattrsToGet)
            throws NamingException {
        final SyncDeltaBuilder sdb = new SyncDeltaBuilder();
        // Set token
        sdb.setToken();
        // Set Delta Type
        sdb.setDeltaType(syncDeltaType);
        javax.naming.directory.Attribute uidAttribute;
        Uid uid = null;
        if (StringUtil.isNotBlank(.getConfiguration().getUidAttribute())) {
            uidAttribute = profile.get(.getConfiguration().getUidAttribute());
            if (uidAttribute != null) {
                uid = new Uid(uidAttribute.get().toString());
            }
        }
        if (uid == null) {
            throw new ConnectorException("UID attribute not found");
        }
        // Set UID
        sdb.setUid(uid);
        // Set Connector Object
        if (. == syncDeltaType) {
            sdb.setObject(.createDeletedObject(entryDNuidprofileoclass));
        } else {
            sdb.setObject(.createConnectorObject(entryDNprofileattrsToGetoclass));
        }
        return sdb.build();
    }
    private void handleInOutEntries(
            final LdapContext ctx,
            final ObjectClass oclass,
            final NamingEnumeration<Stringdns,
            final String filter,
            final SyncResultsHandler handler,
            final ADConfiguration conf,
            final Collection<StringattrsToGet)
            throws NamingException {
        while (dns.hasMoreElements()) {
            // for each new user "in" we must verify custom ldap filter
            handleEntry(ctxoclassdns.next(), filterhandlerconfattrsToGet);
        }
    }
    private void handleEntry(
            final LdapContext ctx,
            final ObjectClass oclass,
            final String dn,
            final String filter,
            final SyncResultsHandler handler,
            final ADConfiguration conf,
            final Collection<StringattrsToGet)
            throws NamingException {
        final Attributes profile = ctx.getAttributes(dn);
        final Attribute objectClasses = profile.get("objectClass");
        if (oclass.is(.) && !objectClasses.contains("user")
                || oclass.is(.) && !objectClasses.contains("group")) {
            .info("Invalid type: skip object {0}"dn);
            return;
        }
        final SyncDeltaType deltaType;
        if (DirSyncUtils.verifyFilter(ctxdnfilter)) {
            if (.isOk()) {
                .ok("Entry {0} - update"dn);
            }
            deltaType = .;
        } else {
            // new memberOf could invalidate the custom filter
            if (.isOk()) {
                .ok("Entry {0} - delete"dn);
            }
            deltaType = .;
        }
        if (deltaType != .
                || (oclass.is(.) && conf.isRetrieveDeletedGroup())
                || (oclass.is(.) && conf.isRetrieveDeletedUser())) {
            handler.handle(getSyncDelta(
                    oclass,
                    dn,
                    deltaType,
                    profile,
                    attrsToGet));
        }
    }
New to GrepCode? Check out our FAQ X