com.aurel.track.util.LdapUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.aurel.track.util.LdapUtil.java

Source

/**
 * Genji Scrum Tool and Issue Tracker
 * Copyright (C) 2015 Steinbeis GmbH & Co. KG Task Management Solutions
    
 * <a href="http://www.trackplus.com">Genji Scrum Tool</a>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

/* $Id:$ */

package com.aurel.track.util;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.SizeLimitExceededException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.PagedResultsControl;
import javax.naming.ldap.PagedResultsResponseControl;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.aurel.track.admin.user.person.PersonBL;
import com.aurel.track.beans.TPersonBean;
import com.aurel.track.beans.TSiteBean;
import com.aurel.track.dbase.HandleHome;
import com.aurel.track.prop.ApplicationBean;

public class LdapUtil {

    public static interface LDAP_CONFIG {
        // enable automatic (quartz job based) synchronization with LDAP
        static String ENABLE_AUTOMATIC_SYNC = "enabled";
        // enable user synchronization with LDAP
        static String ENABLE_USER_SYNC = "enabledUserSync";
        // enable group and group users synchronization with LDAP
        static String ENABLE_GROUP_SYNC = "enabledGroupSync";

        // baseDN for group synchronization
        static String BASE_DN_FOR_GROUP = "baseDnGroup";

        // deactivate users unknown in LDAP
        static String DEACTIVATE_UNKNOWN = "deactivateUnknown";

        // LDAP filter expression for users
        static String LDAP_FILTER_PERSONS = "ldapFilter";
        // LDAP filter expression for groups
        static String LDAP_FILTER_GROUPS = "ldapFilterGroups";
        // first name attribute in LDAP: defaults to gn
        static String FIRST_NAME = "firstName";
        // last name attribute in LDAP: defaults to sn
        static String LAST_NAME = "lastName";
        // e-mail attribute in LDAP: defaults to mail
        static String EMAIL = "email";
        // phone attribute in LDAP: defaults to phone
        static String PHONE = "phone";

        // groupName attribute in LDAP: defaults to cn
        static String GROUP_NAME = "groupName";

        /**
         * The attribute which specifies the members of the group
         */
        static String GROUP_MEMBER = "groupMember";
    }

    static String DEFAULT_GROUP_MEMBER = "member";

    private static String PATH_TO_KEY_STORE;

    static {
        PATH_TO_KEY_STORE = HandleHome.getTrackplus_Home() + File.separator + "keystore" + File.separator
                + "trackplus.ks";
    }

    private final static Logger LOGGER = LogManager.getLogger(LdapUtil.class);
    private static HashMap<String, String> ldapMap = new HashMap<String, String>();

    /**
     * Gets the base URL from a complete URL (possibly with dn)
     * 
     * @param ldapServerURL
     * @return
     */
    public static String getBaseURL(String ldapServerURL) {
        String baseURL = null;
        URI uri = null;
        try {
            uri = new URI(ldapServerURL);
        } catch (URISyntaxException e) {
            LOGGER.warn("Creating an URI from " + ldapServerURL + " failed with " + e.getMessage());
        }
        if (uri != null) {
            // uri.get
            baseURL = uri.getScheme() + "://" + uri.getHost();
            int port = uri.getPort();
            if (port > 0) {
                baseURL += ":" + uri.getPort();
            }
            baseURL += "/";
            LOGGER.debug("Base url from " + ldapServerURL + " is " + baseURL);
        }
        return baseURL;
    }

    /**
     * Returns true if the specified password can be authenticated against
     * Ldap-Server
     * 
     * @param loginName
     *            the loginName of the user
     * @param ppassword
     *            the password to check for
     * @return true if the password is o.k., false if not
     */
    public static boolean authenticate(String loginName, String ppassword) {
        TSiteBean siteBean = ApplicationBean.getInstance().getSiteBean();
        try {
            return authenticate(siteBean, loginName, ppassword);
        } catch (NamingException e) {
            LOGGER.debug("authenticate failed with " + e);
            return false;
        }
    }

    public static boolean authenticate(TSiteBean siteBean, String loginName, String ppassword)
            throws NamingException {
        boolean userIsOK = false;
        ArrayList<String> trace = new ArrayList<String>();

        trace.add("Ldap trying to authenticate user with loginname >" + loginName + "<");

        if (siteBean.getLdapServerURL().startsWith("ldaps:")) {
            System.setProperty("javax.net.ssl.trustStore", PATH_TO_KEY_STORE);
        }
        // get the CN
        String keyDn = getCn(siteBean, loginName);

        try {
            if (keyDn != null) {
                trace.add("Using keyDn >" + keyDn + "<");
                // Set up the environment for creating the initial context
                Hashtable<String, String> env = new Hashtable<String, String>(11);
                env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
                env.put(Context.PROVIDER_URL, siteBean.getLdapServerURL());
                env.put(Context.SECURITY_AUTHENTICATION, "simple");
                env.put(Context.SECURITY_PRINCIPAL, keyDn);
                env.put(Context.SECURITY_CREDENTIALS, ppassword);
                // Create initial context
                DirContext itest = new InitialDirContext(env);
                itest.close();
                // user was validated
                userIsOK = true;
            }
            return userIsOK;
        } catch (NamingException e) {
            for (String msg : trace) {
                LOGGER.warn(msg);
            }
            throw e;
        }
    }

    private static String getCn(String loginName) {
        TSiteBean siteBean = ApplicationBean.getInstance().getSiteBean();
        try {
            return getCn(siteBean, loginName);
        } catch (NamingException e) {
            LOGGER.debug("get common name (CN) for >" + loginName + "< failed with " + e);
            return null;
        }
    }

    /**
     * Returns the CN (common name) for a given login name
     * 
     * @param loginName
     *            the loginName of the user
     * @return CN as a String(if found), or null (else)
     */
    private static String getCn(TSiteBean siteBean, String loginName) throws NamingException {
        String keyDn = null;
        DirContext ctx = getInitialContext(siteBean.getLdapServerURL(), siteBean.getLdapBindDN(),
                siteBean.getLdapBindPassword());
        if (ctx != null) {
            SearchControls ctls = new SearchControls();
            ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            // Search for the user-id
            String searchStr = "(" + siteBean.getLdapAttributeLoginName() + "=" + loginName + ")";
            NamingEnumeration<SearchResult> answer = ctx.search("", searchStr, ctls);
            if (answer.hasMore()) {
                // retrieve the CN
                SearchResult sr = answer.next();
                keyDn = sr.getName();// + "," + ctx.getNameInNamespace();
                LOGGER.debug("Name = " + keyDn);
                String nameInNamespace = ctx.getNameInNamespace();
                LOGGER.debug("Name in namespace " + nameInNamespace);
                if (nameInNamespace != null && nameInNamespace.trim().length() > 0) {
                    keyDn += "," + ctx.getNameInNamespace();
                }
                LOGGER.debug("entry found for LDAP-search >" + searchStr + "<: dn= >" + keyDn + "<!");
                answer.close(); // wo don't need more answers
            } else {
                LOGGER.debug("no entry found for LDAP-search >" + searchStr + "<!");
            }
            ctx.close();
        }
        return keyDn;
    }

    /**
     * Gets the initial context
     * 
     * @param providerUrl
     * @param bindDN
     * @param bindPassword
     * @return
     */
    public static LdapContext getInitialContext(String providerUrl, String bindDN, String bindPassword) {
        List<String> trace = new ArrayList<String>();
        LOGGER.debug("providerURL: " + providerUrl);
        trace.add("Attempting to connect to the LDAP server...");
        if (providerUrl != null && providerUrl.startsWith("ldaps:")) {
            System.setProperty("javax.net.ssl.trustStore", PATH_TO_KEY_STORE);
            trace.add("Using ldaps: with keystore at " + PATH_TO_KEY_STORE);
            File ks = new File(PATH_TO_KEY_STORE);
            if (!ks.exists()) {
                trace.add("*** There is no keystore at " + PATH_TO_KEY_STORE);
            }
        }
        if (providerUrl == null) {
            LOGGER.warn("LDAP provider URL should not be null.");
            return null;
        }
        Hashtable<String, Object> env = new Hashtable<String, Object>();
        if (LOGGER.isDebugEnabled()) {
            env.put("com.sun.jndi.ldape.trace.ber", System.err);
        }
        env.put("java.naming.ldap.version", "3");
        env.put("com.sun.jndi.ldap.connect.timeout", "10000");
        env.put("com.sun.jndi.dns.timeout.initial", "2000");
        env.put("com.sun.jndi.dns.timeout.retries", "3");
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, providerUrl);
        if ((bindDN != null) && !bindDN.equals("")) {
            env.put(Context.SECURITY_AUTHENTICATION, "simple");
            env.put(Context.SECURITY_PRINCIPAL, bindDN);
            env.put(Context.SECURITY_CREDENTIALS, bindPassword);
            LOGGER.debug("bind with bindDN:" + bindDN + " " + "bindPassword=" + bindPassword.replaceAll(".", "*"));
            trace.add("Preparing to bind to the LDAP server with DN = " + bindDN + " and password '****");
        } else {
            LOGGER.debug("bind anonymous");
            trace.add("Preparing to bind anonymously to the LDAP server");
        }
        try {
            return new InitialLdapContext(env, null);
        } catch (NamingException e) {
            for (String msg : trace) {
                LOGGER.error(msg);
            }
            LOGGER.error("Getting the initial ldap context failed with " + e.getMessage());
            LOGGER.debug(ExceptionUtils.getStackTrace(e));
            try {
                new InitialDirContext(env);
            } catch (NamingException e1) {
                LOGGER.error("Getting the initial dir context failed with " + e.getMessage());
                LOGGER.debug(ExceptionUtils.getStackTrace(e));
            }
            return null;
        }
    }

    /**
     * Gets a personBean from LDAP
     * 
     * @param searchResult
     * @param loginAttributeName
     * @param firstNameAttributeName
     * @param lastNameAttributName
     * @param emailAttributeName
     * @param phoneAttributName
     * @return
     */
    public static TPersonBean getPersonBean(SearchResult searchResult, String loginAttributeName,
            String firstNameAttributeName, String lastNameAttributName, String emailAttributeName,
            String phoneAttributName) {
        Attributes attributes = searchResult.getAttributes();
        if (attributes == null) {
            LOGGER.warn("No attributes found in LDAP search result " + searchResult.getName());
            return null;
        }
        TPersonBean personBean = new TPersonBean();
        try {
            Attribute loginAttribute = attributes.get(loginAttributeName);
            if (loginAttribute != null) {
                String loginName = (String) loginAttribute.get();
                LOGGER.debug("Loginname: " + loginName);
                if (loginName == null || "".equals(loginName)) {
                    LOGGER.info("No value for loginame attribute " + loginAttributeName);
                    return null;
                } else {
                    // loginname is mandatory for person
                    personBean.setLoginName(loginName);
                }
            } else {
                LOGGER.info("No loginame attribute " + loginAttributeName);
                return null;
            }
            Attribute emailAttribute = attributes.get(emailAttributeName);
            if (emailAttribute != null) {
                String email = (String) emailAttribute.get();
                LOGGER.debug("E-mail: " + email);
                if (email == null || "".equals(email)) {
                    LOGGER.info("No value for e-mail attribute " + emailAttributeName);
                    // e-mail is mandatory for person
                    return null;
                } else {
                    personBean.setEmail(email);
                }
            } else {
                LOGGER.info("No e-mail attribute " + emailAttributeName);
                return null;
            }
            Attribute firstNameAttribute = attributes.get(firstNameAttributeName);
            if (firstNameAttribute != null) {
                String firstName = (String) firstNameAttribute.get();
                LOGGER.debug("Firstname: " + firstName);
                personBean.setFirstName(firstName);
            }
            Attribute lastNameAttribute = attributes.get(lastNameAttributName);
            if (lastNameAttribute != null) {
                String lastName = (String) lastNameAttribute.get();
                LOGGER.debug("Lastname: " + lastName);
                if (lastName == null || "".equals(lastName)) {
                    LOGGER.info("No value for lastname attribute " + lastNameAttributName);
                    // lastname is mandatory for person
                    return null;
                } else {
                    personBean.setLastName(lastName);
                }
            }
            if (phoneAttributName != null) {
                Attribute phoneAttribute = attributes.get(phoneAttributName);
                if (phoneAttribute != null) {
                    String phone = (String) phoneAttribute.get();
                    LOGGER.debug("Phone: " + phone);
                    personBean.setPhone(phone);
                }
            }
            LOGGER.debug("LDAP entry cn: " + (String) attributes.get("cn").get());
            LOGGER.debug("Processed " + personBean.getLoginName() + " (" + personBean.getFirstName() + " "
                    + personBean.getLastName() + ")");
        } catch (Exception e) {
            LOGGER.warn("Problem setting attributes from LDAP: " + e.getMessage());
            LOGGER.warn("This is probably a configuration error in the LDAP mapping section of quartz-jobs.xml");
            LOGGER.debug(ExceptionUtils.getStackTrace(e));
        }
        return personBean;
    }

    /**
     * Get all ldap groups
     * 
     * @param siteBean
     * @param baseDnGroup
     * @param ldapFilterGroups
     * @param groupAttributeName
     * @param groupToMemberReferencesMap
     * @return
     * @throws Exception
     */
    public static Map<String, TPersonBean> getLdapGroupsByList(String baseURL, TSiteBean siteBean,
            String groupAttributeName, Map<String, List<String>> groupToMemberReferencesMap,
            Map<String, String> groups) throws Exception {
        HashMap<String, TPersonBean> ldapGroupsMap = new HashMap<String, TPersonBean>();
        String bindDN = siteBean.getLdapBindDN();
        String bindPassword = siteBean.getLdapBindPassword();
        String groupMemberAttributName = ldapMap.get(LDAP_CONFIG.GROUP_MEMBER);
        if (groupMemberAttributName == null) {
            LOGGER.debug(
                    "No groupMember attribute defined in quartz-jobs.xml. Fall back to " + DEFAULT_GROUP_MEMBER);
            groupMemberAttributName = DEFAULT_GROUP_MEMBER;
        }
        LdapContext baseContext = getInitialContext(baseURL, bindDN, bindPassword);
        if (baseContext == null) {
            LOGGER.warn("Context is null for baseURL " + baseURL);
            return ldapGroupsMap;
        }
        for (Map.Entry<String, String> groupEntry : groups.entrySet()) {
            String groupName = groupEntry.getKey();
            String groupDN = groupEntry.getValue();
            int index = groupDN.indexOf(",");
            if (index != -1) {
                String searchPart = groupDN.substring(0, index);
                String searchStr = "(" + searchPart + ")";
                String parentDNPart = groupDN.substring(index + 1);
                LdapContext context = (LdapContext) baseContext.lookup(parentDNPart);
                if (context == null) {
                    LOGGER.warn("Context is null after lookup for " + parentDNPart);
                    continue;
                }
                int recordCount = 0;
                SearchControls ctls = null;
                try {
                    // Activate paged results
                    int pageSize = 5;
                    byte[] cookie = null;
                    context.setRequestControls(
                            new Control[] { new PagedResultsControl(pageSize, Control.NONCRITICAL) });
                    int total;
                    // Control the search
                    ctls = new SearchControls();
                    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
                    ctls.setCountLimit((ApplicationBean.getInstance().getMaxNumberOfFullUsers()
                            + ApplicationBean.getInstance().getMaxNumberOfLimitedUsers()) * 3 + 10); // Don't ask for more than we can
                                                                                                                                                                                 // handle anyways
                    do {
                        /* perform the search */
                        NamingEnumeration<SearchResult> results = context.search("", searchStr, ctls);
                        /*
                         * for each entry print out name + all attrs and values
                         */
                        while (results != null && results.hasMore()) {
                            SearchResult searchResult = (SearchResult) results.next();
                            // Attributes atrs = sr.getAttributes();
                            Attributes attributes = searchResult.getAttributes();
                            if (attributes == null) {
                                LOGGER.warn("No attributes found in LDAP search result " + searchResult.getName());
                                continue;
                            }
                            TPersonBean personBean = new TPersonBean();
                            try {
                                personBean.setLoginName(groupName);
                                ldapGroupsMap.put(personBean.getLoginName(), personBean);
                                Attribute memberAttribute = attributes.get(groupMemberAttributName);
                                if (memberAttribute != null) {
                                    NamingEnumeration<?> members = memberAttribute.getAll();
                                    while (members != null && members.hasMore()) {
                                        String memberSearchResult = (String) members.next();
                                        List<String> memberDNList = groupToMemberReferencesMap.get(groupName);
                                        if (memberDNList == null) {
                                            memberDNList = new ArrayList<String>();
                                            groupToMemberReferencesMap.put(groupName, memberDNList);
                                        }
                                        LOGGER.debug("Member found: " + memberSearchResult);
                                        memberDNList.add(memberSearchResult);
                                    }
                                } else {
                                    LOGGER.info("Could not find value(s) for group member attribute "
                                            + groupMemberAttributName + " for group " + groupName);
                                }
                                LOGGER.debug("LDAP entry cn: " + (String) attributes.get("cn").get());
                                LOGGER.debug("Processed group " + groupName);
                            } catch (Exception e) {
                                LOGGER.warn("Problem setting attributes from LDAP: " + e.getMessage());
                                LOGGER.warn(
                                        "This is probably a configuration error in the LDAP mapping section of quartz-jobs.xml");
                                if (LOGGER.isDebugEnabled()) {
                                    LOGGER.debug("Stack trace:", e);
                                }
                            }
                            ++recordCount;
                        }
                        // Examine the paged results control response
                        Control[] controls = context.getResponseControls();
                        if (controls != null) {
                            for (int i = 0; i < controls.length; i++) {
                                if (controls[i] instanceof PagedResultsResponseControl) {
                                    PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
                                    total = prrc.getResultSize();
                                    if (total != 0) {
                                        LOGGER.debug("***************** END-OF-PAGE " + "(total : " + total
                                                + ") *****************\n");
                                    } else {
                                        LOGGER.debug("***************** END-OF-PAGE "
                                                + "(total: unknown) ***************\n");
                                    }
                                    cookie = prrc.getCookie();
                                }
                            }
                        } else {
                            LOGGER.debug("No controls were sent from the server");
                        }
                        // Re-activate paged results
                        context.setRequestControls(
                                new Control[] { new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });

                    } while (cookie != null);
                } catch (SizeLimitExceededException sle) {
                    if (recordCount < ctls.getCountLimit()) {
                        LOGGER.error("Searching LDAP asked for more entries than permitted by the LDAP server.");
                        LOGGER.error("Size limit exceeded error occurred after record " + recordCount + " with "
                                + sle.getMessage());
                        LOGGER.error(
                                "You have to ask your LDAP server admin to increase the limit or specify a more suitable search base or filter.");
                    } else {
                        LOGGER.error("Searching LDAP asked for more entries than permitted by the Genji server ("
                                + recordCount + ").");
                        LOGGER.error(
                                "You have to get more user licenses for Genji or specify a more suitable search base or filter.");
                    }
                    LOGGER.error("The LDAP synchronization is most likely incomplete.");
                } catch (NamingException e) {
                    LOGGER.error("PagedSearch failed.");
                    LOGGER.debug(ExceptionUtils.getStackTrace(e));
                } catch (IOException ie) {
                    LOGGER.error("PagedSearch failed.");
                    LOGGER.debug(ExceptionUtils.getStackTrace(ie));
                } finally {
                    context.close();
                }
            }
        }
        return ldapGroupsMap;
    }

    /**
     * Get all ldap groups
     * 
     * @param siteBean
     * @param baseDnGroup
     * @param ldapFilterGroups
     * @param groupAttributeName
     * @param groupToMemberReferencesMap
     * @return
     * @throws Exception
     */
    public static Map<String, TPersonBean> getLdapGroupsPaged(String baseURL, TSiteBean siteBean,
            String baseDnGroup, String ldapFilterGroups, String groupAttributeName,
            Map<String, List<String>> groupToMemberReferencesMap) throws Exception {
        if (ldapFilterGroups == null || "".equals(ldapFilterGroups) || "*".equals(ldapFilterGroups)) {
            ldapFilterGroups = "(" + groupAttributeName + "=*)";
        }
        String bindDN = siteBean.getLdapBindDN();
        String bindPassword = siteBean.getLdapBindPassword();
        LdapContext context = getInitialContext(baseURL + baseDnGroup, bindDN, bindPassword);
        HashMap<String, TPersonBean> ldapGroupsMap = new HashMap<String, TPersonBean>();
        if (context == null) {
            LOGGER.warn("Context is null");
            return ldapGroupsMap;
        }
        int recordCount = 0;
        SearchControls ctls = null;
        String groupMemberAttributName = ldapMap.get(LDAP_CONFIG.GROUP_MEMBER);
        if (groupMemberAttributName == null) {
            groupMemberAttributName = DEFAULT_GROUP_MEMBER;
        }
        try {
            // Activate paged results
            int pageSize = 5;
            byte[] cookie = null;
            context.setRequestControls(new Control[] { new PagedResultsControl(pageSize, Control.NONCRITICAL) });
            int total;
            // Control the search
            ctls = new SearchControls();
            ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            ctls.setCountLimit((ApplicationBean.getInstance().getMaxNumberOfFullUsers()
                    + ApplicationBean.getInstance().getMaxNumberOfLimitedUsers()) * 3 + 10); // Don't ask for more than we can handle
                                                                                                                                                                         // anyways
            do {
                /* perform the search */
                NamingEnumeration<SearchResult> results = context.search("", ldapFilterGroups, ctls);
                /* for each entry print out name + all attrs and values */
                while (results != null && results.hasMore()) {
                    SearchResult searchResult = (SearchResult) results.next();
                    // Attributes atrs = sr.getAttributes();
                    Attributes attributes = searchResult.getAttributes();
                    if (attributes == null) {
                        LOGGER.warn("No attributes found in LDAP search result " + searchResult.getName());
                        return null;
                    }
                    TPersonBean personBean = new TPersonBean();
                    try {
                        Attribute groupNameAttribute = attributes.get(groupAttributeName);
                        if (groupNameAttribute != null) {
                            String groupName = (String) groupNameAttribute.get();
                            LOGGER.debug("Groupname: " + groupName);
                            if (groupName == null || "".equals(groupName)) {
                                LOGGER.info("No value for group name attribute " + groupAttributeName);
                                return null;
                            } else {
                                personBean.setLoginName(groupName);
                                ldapGroupsMap.put(personBean.getLoginName(), personBean);
                            }
                            Attribute memberAttribute = attributes.get(groupMemberAttributName);
                            if (memberAttribute != null) {
                                NamingEnumeration<?> members = memberAttribute.getAll();
                                while (members != null && members.hasMore()) {
                                    String memberSearchResult = (String) members.next();
                                    List<String> memberDNList = groupToMemberReferencesMap.get(groupName);
                                    if (memberDNList == null) {
                                        memberDNList = new ArrayList<String>();
                                        groupToMemberReferencesMap.put(groupName, memberDNList);
                                    }
                                    memberDNList.add(memberSearchResult);
                                }
                            } else {
                                LOGGER.info("Could not find value(s) for group member attribute "
                                        + groupMemberAttributName + " for group " + groupName);
                            }
                        }
                        LOGGER.debug("LDAP entry cn: " + (String) attributes.get("cn").get());
                        LOGGER.debug("Processed " + personBean.getLoginName() + " (" + personBean.getFirstName()
                                + " " + personBean.getLastName() + ")");
                    } catch (Exception e) {
                        LOGGER.warn("Problem setting attributes from LDAP: " + e.getMessage());
                        LOGGER.warn(
                                "This is probably a configuration error in the LDAP mapping section of quartz-jobs.xml");
                        if (LOGGER.isDebugEnabled()) {
                            LOGGER.debug("Stack trace:", e);
                        }
                    }
                    ++recordCount;
                }
                // Examine the paged results control response
                Control[] controls = context.getResponseControls();
                if (controls != null) {
                    for (int i = 0; i < controls.length; i++) {
                        if (controls[i] instanceof PagedResultsResponseControl) {
                            PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
                            total = prrc.getResultSize();
                            if (total != 0) {
                                LOGGER.debug("***************** END-OF-PAGE " + "(total : " + total
                                        + ") *****************\n");
                            } else {
                                LOGGER.debug(
                                        "***************** END-OF-PAGE " + "(total: unknown) ***************\n");
                            }
                            cookie = prrc.getCookie();
                        }
                    }
                } else {
                    LOGGER.debug("No controls were sent from the server");
                }
                // Re-activate paged results
                context.setRequestControls(
                        new Control[] { new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });

            } while (cookie != null);
        } catch (SizeLimitExceededException sle) {
            if (recordCount < ctls.getCountLimit()) {
                LOGGER.error("Searching LDAP asked for more entries than permitted by the LDAP server.");
                LOGGER.error("Size limit exceeded error occurred after record " + recordCount + " with "
                        + sle.getMessage());
                LOGGER.error(
                        "You have to ask your LDAP server admin to increase the limit or specify a more suitable search base or filter.");
            } else {
                LOGGER.error("Searching LDAP asked for more entries than permitted by the Genji server ("
                        + recordCount + ").");
                LOGGER.error(
                        "You have to get more user licenses for Genji or specify a more suitable search base or filter.");
            }
            LOGGER.error("The LDAP synchronization is most likely incomplete.");
        } catch (NamingException e) {
            LOGGER.error("PagedSearch failed.");
            LOGGER.debug(ExceptionUtils.getStackTrace(e));
        } catch (IOException ie) {
            LOGGER.error("PagedSearch failed.");
            LOGGER.debug(ExceptionUtils.getStackTrace(ie));
        } finally {
            context.close();
        }
        return ldapGroupsMap;
    }

    /**
     * Gets the ldap persons for ldap groups based on the person DNs
     * 
     * @param siteBean
     * @param groups
     * @param groupToMemberReferencesMap
     * @return
     */
    public static Map<String, List<TPersonBean>> getGroupToPersonMaps(String baseURL, TSiteBean siteBean,
            Map<String, TPersonBean> groups, Map<String, List<String>> groupToMemberReferencesMap) {
        String loginAttributeName = siteBean.getLdapAttributeLoginName();
        String bindDN = siteBean.getLdapBindDN();
        String bindPassword = siteBean.getLdapBindPassword();
        Map<String, String> ldapMap = getLdapMap();
        String personFilter = ldapMap.get(LdapUtil.LDAP_CONFIG.LDAP_FILTER_PERSONS);
        boolean hasPersonFilter = false;
        if (personFilter != null && !"".equals(personFilter) && !"*".equals(personFilter)) {
            hasPersonFilter = true;
            if (!(personFilter.startsWith("(") && personFilter.endsWith(")"))) {
                personFilter = "(" + personFilter + ")";
            }
            LOGGER.debug("General user filter expression " + personFilter);
        }
        Map<String, List<TPersonBean>> groupToPersons = new HashMap<String, List<TPersonBean>>();
        if (groupToMemberReferencesMap != null) {
            for (Map.Entry<String, List<String>> groupPersons : groupToMemberReferencesMap.entrySet()) {
                String groupName = groupPersons.getKey();
                List<String> personDNs = groupPersons.getValue();
                if (personDNs != null) {
                    LOGGER.debug("Getting the persons for group " + groupName);
                    List<TPersonBean> personList = new ArrayList<TPersonBean>();
                    groupToPersons.put(groupName, personList);
                    for (String personDN : personDNs) {
                        int index = personDN.indexOf(",");
                        if (index != -1) {
                            String searchPart = personDN.substring(0, index);
                            String searchStr = "(" + searchPart + ")";
                            if (hasPersonFilter) {
                                searchStr = "(&" + personFilter + searchStr + ")";
                            }
                            LOGGER.debug("Search string " + searchStr);
                            String parentDNPart = personDN.substring(index + 1);
                            try {
                                TPersonBean personBean = getLdapUser(baseURL + parentDNPart, bindDN, bindPassword,
                                        loginAttributeName, searchStr);
                                if (personBean != null) {
                                    personList.add(personBean);
                                    LOGGER.debug("Person with dn " + personDN + " found as member of group "
                                            + groupName);
                                }
                            } catch (Exception e) {
                                LOGGER.warn("Getting the person " + personDN + " for group " + groupName
                                        + " failed with " + e.getMessage());
                                LOGGER.debug(ExceptionUtils.getStackTrace(e));
                            }
                        }
                    }
                }
            }
        }
        return groupToPersons;
    }

    /**
     * Gets the ldap persons for ldap groups based on the person DNs
     * 
     * @param siteBean
     * @param groups
     * @param groupToMemberReferencesMap
     * @return
     */
    public static Map<String, List<TPersonBean>> getGroupToPersonMaps1(String baseURL, TSiteBean siteBean,
            Map<String, TPersonBean> groups, Map<String, List<String>> groupToMemberReferencesMap) {
        String loginAttributeName = siteBean.getLdapAttributeLoginName();
        String bindDN = siteBean.getLdapBindDN();
        String bindPassword = siteBean.getLdapBindPassword();
        Map<String, String> ldapMap = getLdapMap();
        String personFilter = ldapMap.get(LdapUtil.LDAP_CONFIG.LDAP_FILTER_PERSONS);
        boolean hasPersonFilter = false;
        if (personFilter != null && !"".equals(personFilter) && !"*".equals(personFilter)) {
            hasPersonFilter = true;
            if (!(personFilter.startsWith("(") && personFilter.endsWith(")"))) {
                personFilter = "(" + personFilter + ")";
            }
            LOGGER.debug("General user filter expression " + personFilter);
        }
        Map<String, List<TPersonBean>> groupToPersons = new HashMap<String, List<TPersonBean>>();
        if (groupToMemberReferencesMap != null) {
            for (Map.Entry<String, List<String>> groupPersons : groupToMemberReferencesMap.entrySet()) {
                String groupName = groupPersons.getKey();
                List<String> personDNs = groupPersons.getValue();
                Map<String, List<String>> parentDNPartToPersonSearchStrings = new HashMap<String, List<String>>();
                if (personDNs != null) {
                    LOGGER.debug("Getting the persons for group " + groupName);
                    for (String personDN : personDNs) {
                        int index = personDN.indexOf(",");
                        if (index != -1) {
                            String searchPart = personDN.substring(0, index);
                            String searchStr = "(" + searchPart + ")";
                            if (hasPersonFilter) {
                                searchStr = "(&" + personFilter + searchStr + ")";
                            }
                            String parentDNPart = personDN.substring(index + 1);
                            List<String> personSearchStrings = parentDNPartToPersonSearchStrings.get(parentDNPart);
                            if (personSearchStrings == null) {
                                personSearchStrings = new LinkedList<String>();
                                parentDNPartToPersonSearchStrings.put(parentDNPart, personSearchStrings);
                            }
                            personSearchStrings.add(searchStr);
                        }
                    }
                }
                List<TPersonBean> personsInGroup = new LinkedList<TPersonBean>();
                LdapContext baseContext = getInitialContext(baseURL, bindDN, bindPassword);
                if (baseContext == null) {
                    LOGGER.warn("Context is null for base url " + baseURL);
                    continue;
                }
                for (Map.Entry<String, List<String>> parentDnToPersonSearchStrings : parentDNPartToPersonSearchStrings
                        .entrySet()) {
                    String parentDn = parentDnToPersonSearchStrings.getKey();
                    List<String> searchStrs = parentDnToPersonSearchStrings.getValue();
                    if (searchStrs == null || searchStrs.isEmpty()) {
                        continue;
                    }
                    LdapContext ldapContext = null;
                    try {
                        LOGGER.debug(
                                "Number of persons searched for parentDn " + parentDn + ": " + searchStrs.size());
                        ldapContext = (LdapContext) baseContext.lookup(parentDn);
                        if (ldapContext == null) {
                            LOGGER.warn("Lookup context is null for " + parentDn);
                            continue;
                        }
                        List<TPersonBean> personsInParentDN = getLdapUsers(ldapContext, loginAttributeName,
                                searchStrs);
                        if (personsInParentDN != null) {
                            LOGGER.debug("Number of persons found for parentDn " + parentDn + ": "
                                    + personsInParentDN.size());
                            personsInGroup.addAll(personsInParentDN);
                        }
                    } catch (Exception e) {
                        LOGGER.warn("Getting the persons with parentDn  " + parentDn + " for group " + groupName
                                + " failed with " + e.getMessage());
                        LOGGER.debug(ExceptionUtils.getStackTrace(e));
                    } finally {
                        try {
                            if (ldapContext != null) {
                                ldapContext.close();
                            }
                        } catch (NamingException e) {
                            LOGGER.warn("Closing the context with " + parentDn + " for group " + groupName
                                    + " failed with " + e.getMessage());
                            LOGGER.debug(ExceptionUtils.getStackTrace(e));
                        }
                    }
                }
                groupToPersons.put(groupName, personsInGroup);
                if (baseContext != null) {
                    try {
                        baseContext.close();
                    } catch (NamingException e) {
                        LOGGER.warn("Closing the base context with failed with " + e.getMessage());
                        LOGGER.debug(ExceptionUtils.getStackTrace(e));
                    }
                }
            }
        }
        return groupToPersons;
    }

    /**
     * Returns a HashMap <login name, TPersonBean> for all LDAP objects found in
     * the directory und the DN configured in the Genji server configuration.
     * 
     * @return Map with <login name, TPersonBean>
     */
    public static HashMap<String, TPersonBean> getAllLdapPersonsPaged(TSiteBean siteBean, String filter)
            throws Exception {
        if (filter == null || "".equals(filter) || "*".equals(filter)) {
            filter = siteBean.getLdapAttributeLoginName() + "=*";
        }
        if (!(filter.startsWith("(") && filter.endsWith(")"))) {
            filter = "(" + filter + ")";
        }
        LOGGER.debug("User filter expression " + filter);
        String bindDN = siteBean.getLdapBindDN();
        String bindPassword = siteBean.getLdapBindPassword();
        HashMap<String, TPersonBean> ldapPersonsMap = new HashMap<String, TPersonBean>();
        LdapContext context = getInitialContext(siteBean.getLdapServerURL(), bindDN, bindPassword);
        if (context == null) {
            return ldapPersonsMap;
        }
        int recordCount = 0;
        // Create initial context
        // Control the search
        SearchControls ctls = null;
        try {
            // Activate paged results
            int pageSize = 5;
            byte[] cookie = null;
            context.setRequestControls(new Control[] { new PagedResultsControl(pageSize, Control.NONCRITICAL) });
            int total;
            // Control the search
            ctls = new SearchControls();
            ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            ctls.setCountLimit((ApplicationBean.getInstance().getMaxNumberOfFullUsers()
                    + ApplicationBean.getInstance().getMaxNumberOfLimitedUsers()) * 3 + 10); // Don't ask for more than we can handle
                                                                                                                                                                         // anyways
            if (ldapMap == null || ldapMap.isEmpty()) {
                LOGGER.error("There is no LDAP mapping in quartz-jobs.xml. Please provide!");
                return null;
            }
            String firstNameAttributeName = ldapMap.get(LdapUtil.LDAP_CONFIG.FIRST_NAME);
            String lastNameAttributName = ldapMap.get(LdapUtil.LDAP_CONFIG.LAST_NAME);
            String emailAttributeName = ldapMap.get(LdapUtil.LDAP_CONFIG.EMAIL);
            String phoneAttributName = ldapMap.get(LdapUtil.LDAP_CONFIG.PHONE);
            String loginAttributeName = siteBean.getLdapAttributeLoginName();
            do {
                /* perform the search */
                NamingEnumeration<SearchResult> results = context.search("", filter, ctls);
                /* for each entry print out name + all attrs and values */
                while (results != null && results.hasMore()) {
                    SearchResult sr = (SearchResult) results.next();
                    // Attributes atrs = sr.getAttributes();
                    TPersonBean personBean = getPersonBean(sr, loginAttributeName, firstNameAttributeName,
                            lastNameAttributName, emailAttributeName, phoneAttributName);
                    if (personBean != null) {
                        ldapPersonsMap.put(personBean.getLoginName(), personBean);
                    }
                    ++recordCount;
                }
                // Examine the paged results control response
                Control[] controls = context.getResponseControls();
                if (controls != null) {
                    for (int i = 0; i < controls.length; i++) {
                        if (controls[i] instanceof PagedResultsResponseControl) {
                            PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
                            total = prrc.getResultSize();
                            if (total != 0) {
                                LOGGER.debug("***************** END-OF-PAGE " + "(total : " + total
                                        + ") *****************\n");
                            } else {
                                LOGGER.debug(
                                        "***************** END-OF-PAGE " + "(total: unknown) ***************\n");
                            }
                            cookie = prrc.getCookie();
                        }
                    }
                } else {
                    LOGGER.debug("No controls were sent from the server");
                }
                // Re-activate paged results
                context.setRequestControls(
                        new Control[] { new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });

            } while (cookie != null);
        } catch (SizeLimitExceededException sle) {
            if (recordCount < ctls.getCountLimit()) {
                LOGGER.error("Searching LDAP asked for more entries than permitted by the LDAP server.");
                LOGGER.error("Size limit exceeded error occurred after record " + recordCount + " with "
                        + sle.getMessage());
                LOGGER.error(
                        "You have to ask your LDAP server admin to increase the limit or specify a more suitable search base or filter.");
            } else {
                LOGGER.error("Searching LDAP asked for more entries than permitted by the Genji server ("
                        + recordCount + ").");
                LOGGER.error(
                        "You have to get more user licenses for Genji or specify a more suitable search base or filter.");
            }
            LOGGER.error("The LDAP synchronization is most likely incomplete.");
        } catch (NamingException e) {
            LOGGER.error("PagedSearch failed.");
            LOGGER.debug(ExceptionUtils.getStackTrace(e));
        } catch (IOException ie) {
            LOGGER.error("PagedSearch failed.");
            LOGGER.debug(ExceptionUtils.getStackTrace(ie));
        } finally {
            if (context != null) {
                context.close();
            }
        }
        return ldapPersonsMap;
    }

    /**
     * Check if a given login name can be found on the Ldap-server
     * 
     * @param loginName
     *            , the loginName of the user
     * @return true, if loginname is found
     */
    public static boolean isOnLdapServer(String loginName) {
        return getCn(loginName) != null;
    }

    /**
     * Set the mapping table for mapping between LDAP directory attributes and
     * Track user database attributes.
     * 
     * @param theMap
     */
    public static void setLdapMap(HashMap theMap) {
        ldapMap = theMap;
    }

    /**
     * Set the mapping table for mapping between LDAP directory attributes and
     * Track user database attributes.
     * 
     * @param theMap
     */
    public static Map getLdapMap() {
        return ldapMap;
    }

    static TPersonBean getLdapUser(String providerUrl, String bindDN, String bindPassword,
            String loginAttributeName, String searchStr) throws Exception {
        LdapContext ctx = null;
        try {
            ctx = getInitialContext(providerUrl, bindDN, bindPassword);
            if (ctx == null) {
                LOGGER.warn("The context is null");
            }
            // Control the search
            SearchControls ctls = new SearchControls();
            ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            // Don't ask for more than we can handle anyways
            if (ldapMap == null || ldapMap.isEmpty()) {
                LOGGER.error("There is no LDAP mapping in quartz-jobs.xml. Please provide!");
                return null;
            }
            String firstNameAttributeName = ldapMap.get(LdapUtil.LDAP_CONFIG.FIRST_NAME);
            String lastNameAttributName = ldapMap.get(LdapUtil.LDAP_CONFIG.LAST_NAME);
            String emailAttributeName = ldapMap.get(LdapUtil.LDAP_CONFIG.EMAIL);
            String phoneAttributName = ldapMap.get(LdapUtil.LDAP_CONFIG.PHONE);
            NamingEnumeration<SearchResult> results = ctx.search("", searchStr, ctls);
            /* for each entry print out name + all attrs and values */
            while (results != null && results.hasMore()) {
                SearchResult sr = (SearchResult) results.next();
                return getPersonBean(sr, loginAttributeName, firstNameAttributeName, lastNameAttributName,
                        emailAttributeName, phoneAttributName);
            }
        } catch (NamingException e) {
            LOGGER.warn(
                    "Searching from " + providerUrl + " by filter " + searchStr + " failed with " + e.getMessage());
            LOGGER.debug(ExceptionUtils.getStackTrace(e));
        } finally {
            if (ctx != null) {
                ctx.close();
            }
        }
        return null;
    }

    /**
     * Gets the LDAP users
     * 
     * @param ctx
     * @param loginAttributeName
     * @param searchStrs
     * @return
     */
    static List<TPersonBean> getLdapUsers(LdapContext ctx, String loginAttributeName, List<String> searchStrs) {
        List<TPersonBean> personBeans = new LinkedList<TPersonBean>();
        if (ldapMap == null || ldapMap.isEmpty()) {
            LOGGER.error("There is no LDAP mapping in quartz-jobs.xml. Please provide!");
            return personBeans;
        }
        String firstNameAttributeName = ldapMap.get(LdapUtil.LDAP_CONFIG.FIRST_NAME);
        String lastNameAttributName = ldapMap.get(LdapUtil.LDAP_CONFIG.LAST_NAME);
        String emailAttributeName = ldapMap.get(LdapUtil.LDAP_CONFIG.EMAIL);
        String phoneAttributName = ldapMap.get(LdapUtil.LDAP_CONFIG.PHONE);
        for (String searchStr : searchStrs) {
            LOGGER.debug("Searching by filter " + searchStr);
            SearchControls ctls = new SearchControls();
            ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            try {
                NamingEnumeration<SearchResult> results = ctx.search("", searchStr, ctls);
                while (results != null && results.hasMore()) {
                    SearchResult sr = (SearchResult) results.next();
                    TPersonBean personBean = getPersonBean(sr, loginAttributeName, firstNameAttributeName,
                            lastNameAttributName, emailAttributeName, phoneAttributName);
                    if (personBean != null) {
                        LOGGER.debug("Search successful " + searchStr);
                        personBeans.add(personBean);
                    }
                }
            } catch (NamingException e) {
                LOGGER.warn("Search failed with " + e.getMessage());
                LOGGER.debug(ExceptionUtils.getStackTrace(e));
            }
        }
        return personBeans;
    }

    /**
     * Synchronizes the list of users in the Genji database with a HashMap of
     * login names and TPersonBeans.
     * 
     * @param ldapPersons
     *            a map with login names and their corresponding TPersonBeans
     * 
     */
    public static void synchronizeUserList(Map<String, TPersonBean> ldapPersons) throws Exception {
        List<TPersonBean> dbasePersons = PersonBL.loadPersons();
        Map<String, TPersonBean> dbMap = new HashMap<String, TPersonBean>();
        for (TPersonBean dbasePerson : dbasePersons) {
            dbMap.put(dbasePerson.getLoginName(), dbasePerson);
        }
        /* Compare all LDAP entries with Genji entries. If not found add. */
        /*
         * If deactivated, keep deactivated. If some values changed, merge
         * changes.
         */
        int count = 0;
        for (String key : ldapPersons.keySet()) {
            TPersonBean ldapPerson = ldapPersons.get(key);
            String ldapLoginame = ldapPerson.getLoginName();
            String ldapFirstname = ldapPerson.getFirstName();
            String ldapLastname = ldapPerson.getLastName();
            String ldapEmail = ldapPerson.getEmail();
            String phone = ldapPerson.getPhone();
            TPersonBean dbPerson = dbMap.get(ldapLoginame);
            boolean saveNeeded = false;
            if (dbPerson != null) {
                saveNeeded = !PersonBL.isLdapPersonSame(dbPerson, ldapPerson);
                if (saveNeeded) {
                    PersonBL.updateLdapPerson(dbPerson, ldapFirstname, ldapLastname, ldapEmail, phone);
                    LOGGER.info("Existing user " + ldapFirstname + " " + ldapLastname + " (" + ldapEmail
                            + ") to be changed in Genji database.");
                }
            } else {
                saveNeeded = true;
                dbPerson = PersonBL.createLdapPerson(ldapLoginame, ldapFirstname, ldapLastname, ldapEmail, phone);
                ++count;
                LOGGER.info("Adding user " + ldapPerson.getFirstName() + " " + ldapPerson.getLastName() + " ("
                        + ldapPerson.getEmail() + ") to Genji database.");
            }
            if (saveNeeded) {
                PersonBL.saveAndAddMenuFilters(dbPerson);
            }
        }
        if (count > 0) {
            ApplicationBean.getInstance().setActualUsers();
        }
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("User sync results for " + ldapPersons.size() + " ldap persons:");
            if (count == 0) {
                LOGGER.info("LDAP directory users in sync with Genji database.");
            } else {
                LOGGER.info(count + " user(s) from LDAP directory added to Genji database.");
            }
        }
    }

    /**
     * Synchronizes the list of users in the Genji database with a HashMap of
     * login names and TPersonBeans.
     * 
     * @param ldapPersons
     *            a map with login names and their corresponding TPersonBeans
     * 
     */
    public static void deactivateUsers(Map<String, TPersonBean> ldapPersons) throws Exception {
        List<TPersonBean> dbasePersons = PersonBL.loadActivePersons();
        if (dbasePersons != null && ldapPersons != null) {
            LOGGER.info("Number of users found on LDAP server: " + ldapPersons.size());
            LOGGER.info("Number of active users found in Genji after LDAP sync: " + dbasePersons.size());
            int count = 0;
            List<Integer> deactivate = new ArrayList<Integer>();
            boolean isForceLDAP = ApplicationBean.getInstance().getSiteBean().getIsForceLdap();
            for (TPersonBean dbasePerson : dbasePersons) {
                String loginName = dbasePerson.getLoginName();
                if (!ldapPersons.containsKey(loginName) && (isForceLDAP || dbasePerson.isLdapUser())) {
                    String lname = loginName.toLowerCase();
                    if (TPersonBean.ADMIN_USER.equals(lname) || TPersonBean.GUEST_USER.equals(lname)
                            || dbasePerson.getObjectID().intValue() <= 100) {
                        LOGGER.debug("We do not deactivate admin, guest, or anything with OID below 100");
                    } else {
                        deactivate.add(dbasePerson.getObjectID());
                        count++;
                        LOGGER.debug("Deactivating " + lname);
                    }
                }
            }
            if (count > 0) {
                PersonBL.activateDeactivatePersons(deactivate, true);
                LOGGER.info(count + " user(s) were deactivated");
            } else {
                LOGGER.info("No user were deactivated");
            }
        }
    }

    /**
     * Gets all persons for a group
     * 
     * @param groups
     * @param siteBean
     * @param filter
     * @return
     * @throws Exception
     */
    static List<TPersonBean> getAllLdapUsersDescendants(String providerUrl, String bindDN, String bindPassword,
            String loginAttributeName, String filter) throws Exception {
        List<TPersonBean> personBeans = new ArrayList<TPersonBean>();
        if (filter == null || "".equals(filter) || "*".equals(filter)) {
            filter = loginAttributeName + "=*";
        }
        int recordCount = 0;
        SearchControls ctls = null;
        LdapContext ctx = null;
        try {
            ctx = getInitialContext(providerUrl, bindDN, bindPassword);
            if (ctx == null) {
                return personBeans;
            }
            // Activate paged results
            int pageSize = 5;
            // TODO replace for GROOVY
            ctx.setRequestControls(new Control[] { new PagedResultsControl(pageSize, Control.NONCRITICAL) });
            int total;
            String searchStr = "(" + filter + ")";
            // Control the search
            ctls = new SearchControls();
            ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            ctls.setCountLimit((ApplicationBean.getInstance().getMaxNumberOfFullUsers()
                    + ApplicationBean.getInstance().getMaxNumberOfLimitedUsers()) * 3 + 10); // Don't ask for more than we can handle
                                                                                                                                                                         // anyways
            if (ldapMap == null || ldapMap.isEmpty()) {
                LOGGER.error("There is no LDAP mapping in quartz-jobs.xml. Please provide!");
                return personBeans;
            }
            String firstNameAttributeName = ldapMap.get("firstName");
            String lastNameAttributName = ldapMap.get("lastName");
            String emailAttributeName = ldapMap.get("email");
            String phoneAttributName = ldapMap.get("phone");
            byte[] cookie = null;
            // TODO replace for GROOVY
            cookie = new byte[] {};
            // cookie = [] as byte[];
            while (cookie != null) {
                NamingEnumeration<SearchResult> results = ctx.search("", searchStr, ctls);
                while (results != null && results.hasMore()) {
                    SearchResult sr = (SearchResult) results.next();
                    TPersonBean personBean = getPersonBean(sr, loginAttributeName, firstNameAttributeName,
                            lastNameAttributName, emailAttributeName, phoneAttributName);
                    if (personBean != null) {
                        personBeans.add(personBean);
                        ++recordCount;
                    }
                }
                // Examine the paged results control response
                Control[] controls = ctx.getResponseControls();
                if (controls != null) {
                    for (int i = 0; i < controls.length; i++) {
                        if (controls[i] instanceof PagedResultsResponseControl) {
                            PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
                            total = prrc.getResultSize();
                            if (total != 0) {
                                LOGGER.debug("***************** END-OF-PAGE " + "(total : " + total
                                        + ") *****************\n");
                            } else {
                                LOGGER.debug(
                                        "***************** END-OF-PAGE " + "(total: unknown) ***************\n");
                            }
                            cookie = prrc.getCookie();
                        }
                    }
                } else {
                    LOGGER.debug("No controls were sent from the server");
                }
                // Re-activate paged results
                // TODO replace for GROOVY
                ctx.setRequestControls(
                        new Control[] { new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
            }
        } catch (SizeLimitExceededException sle) {
            if (recordCount < ctls.getCountLimit()) {
                LOGGER.error("Searching LDAP asked for more entries than permitted by the LDAP server.");
                LOGGER.error("Size limit exceeded error occurred after record " + recordCount + " with "
                        + sle.getMessage());
                LOGGER.error(
                        "You have to ask your LDAP server admin to increase the limit or specify a more suitable search base or filter.");
            } else {
                LOGGER.error("Searching LDAP asked for more entries than permitted by the Genji server ("
                        + recordCount + ").");
                LOGGER.error(
                        "You have to get more user licenses for Genji or specify a more suitable search base or filter.");
            }
            LOGGER.error("The LDAP synchronization is most likely incomplete.");
        } catch (NamingException e) {
            LOGGER.error("PagedSearch failed.");
            LOGGER.debug(ExceptionUtils.getStackTrace(e));
        } catch (IOException ie) {
            LOGGER.error("PagedSearch failed.");
            LOGGER.debug(ExceptionUtils.getStackTrace(ie));
        } finally {
            if (ctx != null) {
                ctx.close();
            }
        }
        return personBeans;
    }

}