/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.ranger.ldapusersync.process;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;

import javax.naming.Context;
import javax.naming.InvalidNameException;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
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 javax.naming.ldap.StartTlsRequest;
import javax.naming.ldap.StartTlsResponse;

import org.apache.log4j.Logger;
import org.apache.ranger.unixusersync.config.UserGroupSyncConfig;
import org.apache.ranger.usergroupsync.AbstractUserGroupSource;
import org.apache.ranger.usergroupsync.UserGroupSink;

public class LdapUserGroupBuilder extends AbstractUserGroupSource {

	private static final Logger LOG = Logger.getLogger(LdapUserGroupBuilder.class);

	private static final int PAGE_SIZE = 500;

	private String ldapUrl;
	private String ldapBindDn;
	private String ldapBindPassword;
	private String ldapAuthenticationMechanism;
	private String ldapReferral;
	private String searchBase;

	private String[] userSearchBase;
	private String userNameAttribute;
	private int userSearchScope;
	private String userObjectClass;
	private String userSearchFilter;
	private String extendedUserSearchFilter;
	private SearchControls userSearchControls;
	private Set<String> userGroupNameAttributeSet;

	private boolean pagedResultsEnabled = true;
	private int pagedResultsSize = PAGE_SIZE;

	private boolean groupSearchFirstEnabled;
	private boolean userSearchEnabled;
	private boolean groupSearchEnabled = true;
	private String[] groupSearchBase;
	private int groupSearchScope;
	private String groupObjectClass;
	private String groupSearchFilter;
	private String extendedGroupSearchFilter;
	private String extendedAllGroupsSearchFilter;
	private SearchControls groupSearchControls;
	private String groupMemberAttributeName;
	private String groupNameAttribute;
    private int groupHierarchyLevels;

	private LdapContext ldapContext;
	private StartTlsResponse tls;

	private boolean userNameCaseConversionFlag;
	private boolean groupNameCaseConversionFlag;
	private boolean userNameLowerCaseFlag;
	private boolean groupNameLowerCaseFlag;

	private boolean groupUserMapSyncEnabled;

	private Map<String, UserInfo> userGroupMap;
    //private Set<String> firstGroupDNs;

	public static void main(String[] args) throws Throwable {
		LdapUserGroupBuilder  ugBuilder = new LdapUserGroupBuilder();
		ugBuilder.init();
	}

	public LdapUserGroupBuilder() {
		super();
		LOG.info("LdapUserGroupBuilder created");

		String userNameCaseConversion = config.getUserNameCaseConversion();

		if (UserGroupSyncConfig.UGSYNC_NONE_CASE_CONVERSION_VALUE.equalsIgnoreCase(userNameCaseConversion)) {
			userNameCaseConversionFlag = false;
		}
		else {
			userNameCaseConversionFlag = true;
			userNameLowerCaseFlag = UserGroupSyncConfig.UGSYNC_LOWER_CASE_CONVERSION_VALUE.equalsIgnoreCase(userNameCaseConversion);
		}

		String groupNameCaseConversion = config.getGroupNameCaseConversion();

		if (UserGroupSyncConfig.UGSYNC_NONE_CASE_CONVERSION_VALUE.equalsIgnoreCase(groupNameCaseConversion)) {
			groupNameCaseConversionFlag = false;
		}
		else {
			groupNameCaseConversionFlag = true;
			groupNameLowerCaseFlag = UserGroupSyncConfig.UGSYNC_LOWER_CASE_CONVERSION_VALUE.equalsIgnoreCase(groupNameCaseConversion);
		}
	}

	@Override
	public void init() throws Throwable{
		setConfig();
	}

	private void createLdapContext() throws Throwable {
		Properties env = new Properties();
		env.put(Context.INITIAL_CONTEXT_FACTORY,
				"com.sun.jndi.ldap.LdapCtxFactory");
		env.put(Context.PROVIDER_URL, ldapUrl);
		if (ldapUrl.startsWith("ldaps") && (config.getSSLTrustStorePath() != null && !config.getSSLTrustStorePath().trim().isEmpty())) {
			env.put("java.naming.ldap.factory.socket", "org.apache.ranger.ldapusersync.process.CustomSSLSocketFactory");
		}

		ldapContext = new InitialLdapContext(env, null);
		if (!ldapUrl.startsWith("ldaps")) {
			if (config.isStartTlsEnabled()) {
				tls = (StartTlsResponse) ldapContext.extendedOperation(new StartTlsRequest());
				if (config.getSSLTrustStorePath() != null && !config.getSSLTrustStorePath().trim().isEmpty()) {
					tls.negotiate(CustomSSLSocketFactory.getDefault());
				} else {
					tls.negotiate();
				}
				LOG.info("Starting TLS session...");
			}
		}

		ldapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, ldapBindDn);
		ldapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, ldapBindPassword);
		ldapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, ldapAuthenticationMechanism);
		ldapContext.addToEnvironment(Context.REFERRAL, ldapReferral);
	}

	private void setConfig() throws Throwable {
		LOG.info("LdapUserGroupBuilder initialization started");

		groupSearchFirstEnabled =   config.isGroupSearchFirstEnabled();
		userSearchEnabled =   config.isUserSearchEnabled();
		groupSearchEnabled =   config.isGroupSearchEnabled();
		ldapUrl = config.getLdapUrl();
		ldapBindDn = config.getLdapBindDn();
		ldapBindPassword = config.getLdapBindPassword();
		ldapAuthenticationMechanism = config.getLdapAuthenticationMechanism();
		ldapReferral = config.getContextReferral();
		searchBase = config.getSearchBase();

		userSearchBase = config.getUserSearchBase().split(";");
		userSearchScope = config.getUserSearchScope();
		userObjectClass = config.getUserObjectClass();
		userSearchFilter = config.getUserSearchFilter();
		extendedUserSearchFilter = "(objectclass=" + userObjectClass + ")";
		if (userSearchFilter != null && !userSearchFilter.trim().isEmpty()) {
			String customFilter = userSearchFilter.trim();
			if (!customFilter.startsWith("(")) {
				customFilter = "(" + customFilter + ")";
			}

			extendedUserSearchFilter = "(&" + extendedUserSearchFilter + customFilter + ")";
		}

		userNameAttribute = config.getUserNameAttribute();

		Set<String> userSearchAttributes = new HashSet<String>();
		userSearchAttributes.add(userNameAttribute);
		// For Group based search, user's group name attribute should not be added to the user search attributes
		if (!groupSearchFirstEnabled && !groupSearchEnabled) {
			userGroupNameAttributeSet = config.getUserGroupNameAttributeSet();
			for (String useGroupNameAttribute : userGroupNameAttributeSet) {
				userSearchAttributes.add(useGroupNameAttribute);
			}
		}

		userSearchControls = new SearchControls();
		userSearchControls.setSearchScope(userSearchScope);
		userSearchControls.setReturningAttributes(userSearchAttributes.toArray(
                new String[userSearchAttributes.size()]));

		pagedResultsEnabled =   config.isPagedResultsEnabled();
		pagedResultsSize =   config.getPagedResultsSize();

		groupSearchBase = config.getGroupSearchBase().split(";");
		groupSearchScope = config.getGroupSearchScope();
		groupObjectClass = config.getGroupObjectClass();
		groupSearchFilter = config.getGroupSearchFilter();
		groupMemberAttributeName =  config.getUserGroupMemberAttributeName();
		groupNameAttribute = config.getGroupNameAttribute();
        groupHierarchyLevels = config.getGroupHierarchyLevels();

		extendedGroupSearchFilter = "(objectclass=" + groupObjectClass + ")";
		if (groupSearchFilter != null && !groupSearchFilter.trim().isEmpty()) {
			String customFilter = groupSearchFilter.trim();
			if (!customFilter.startsWith("(")) {
				customFilter = "(" + customFilter + ")";
			}
			extendedGroupSearchFilter = extendedGroupSearchFilter + customFilter;
		}
		extendedAllGroupsSearchFilter = "(&"  + extendedGroupSearchFilter + ")";
		if (!groupSearchFirstEnabled) {
			extendedGroupSearchFilter =  "(&"  + extendedGroupSearchFilter + "(|(" + groupMemberAttributeName + "={0})(" + groupMemberAttributeName + "={1})))";
		}
		groupUserMapSyncEnabled = config.isGroupUserMapSyncEnabled();

		groupSearchControls = new SearchControls();
		groupSearchControls.setSearchScope(groupSearchScope);

		Set<String> groupSearchAttributes = new HashSet<String>();
		groupSearchAttributes.add(groupNameAttribute);
		groupSearchAttributes.add(groupMemberAttributeName);

		groupSearchControls.setReturningAttributes(groupSearchAttributes.toArray(
				new String[groupSearchAttributes.size()]));

		if (LOG.isInfoEnabled()) {
			LOG.info("LdapUserGroupBuilder initialization completed with --  "
					+ "ldapUrl: " + ldapUrl
					+ ",  ldapBindDn: " + ldapBindDn
					+ ",  ldapBindPassword: ***** "
					+ ",  ldapAuthenticationMechanism: " + ldapAuthenticationMechanism
					+ ",  searchBase: " + searchBase
					+ ",  userSearchBase: " + Arrays.toString(userSearchBase)
					+ ",  userSearchScope: " + userSearchScope
					+ ",  userObjectClass: " + userObjectClass
					+ ",  userSearchFilter: " + userSearchFilter
					+ ",  extendedUserSearchFilter: " + extendedUserSearchFilter
					+ ",  userNameAttribute: " + userNameAttribute
					+ ",  userSearchAttributes: " + userSearchAttributes
					+ ",  userGroupNameAttributeSet: " + userGroupNameAttributeSet
					+ ",  pagedResultsEnabled: " + pagedResultsEnabled
					+ ",  pagedResultsSize: " + pagedResultsSize
					+ ",  groupSearchEnabled: " + groupSearchEnabled
					+ ",  groupSearchBase: " + Arrays.toString(groupSearchBase)
					+ ",  groupSearchScope: " + groupSearchScope
					+ ",  groupObjectClass: " + groupObjectClass
					+ ",  groupSearchFilter: " + groupSearchFilter
					+ ",  extendedGroupSearchFilter: " + extendedGroupSearchFilter
					+ ",  extendedAllGroupsSearchFilter: " + extendedAllGroupsSearchFilter
					+ ",  groupMemberAttributeName: " + groupMemberAttributeName
					+ ",  groupNameAttribute: " + groupNameAttribute
					+ ", groupSearchAttributes: " + groupSearchAttributes
					+ ",  groupUserMapSyncEnabled: " + groupUserMapSyncEnabled
					+ ", groupSearchFirstEnabled: " + groupSearchFirstEnabled
					+ ", userSearchEnabled: " + userSearchEnabled
					+ ",  ldapReferral: " + ldapReferral
					);
		}

	}

	private void closeLdapContext() throws Throwable {
		if (tls != null) {
			tls.close();
		}
		if (ldapContext != null) {
			ldapContext.close();
		}
	}

	@Override
	public boolean isChanged() {
		// we do not want to get the full ldap dit and check whether anything has changed
		return true;
	}

	@Override
	public void updateSink(UserGroupSink sink) throws Throwable {
		LOG.info("LDAPUserGroupBuilder updateSink started");
		userGroupMap = new HashMap<String, UserInfo>();

		if (!groupSearchFirstEnabled) {
			LOG.info("Performing user search first");
			getUsers(sink);
			LOG.debug("Total No. of users saved = " + userGroupMap.size());
			if (!groupSearchEnabled && groupHierarchyLevels > 0) {
				getRootDN();
			}
            //Iterator<UserInfo> userInfoIterator = userGroupMap.
			for (UserInfo userInfo : userGroupMap.values()) {
				String userName = userInfo.getUserName();
				if (groupSearchEnabled) {
					// Perform group search
					LOG.info("groupSearch is enabled, would search for groups and compute memberships");
                    //firstGroupDNs = new HashSet<String>();
					getGroups(sink, userInfo);
				}
                if (groupHierarchyLevels > 0) {
                    LOG.debug("Going through group hierarchy for nested group evaluation");
                    goUpGroupHierarchyLdap(userInfo.getGroupDNs(), groupHierarchyLevels - 1, userInfo);
                    LOG.debug("Completed group hierarchy computation");
                }
				List<String> groupList = userInfo.getGroups();
                LOG.debug("updateSink(): group list for " + userName + " = " + groupList);
				if (userNameCaseConversionFlag) {
					if (userNameLowerCaseFlag) {
						userName = userName.toLowerCase();
					}
					else {
						userName = userName.toUpperCase();
					}
				}

				if (userNameRegExInst != null) {
					userName = userNameRegExInst.transform(userName);
				}
				try {
					sink.addOrUpdateUser(userName, groupList);
				} catch (Throwable t) {
					LOG.error("sink.addOrUpdateUser failed with exception: " + t.getMessage()
					+ ", for user: " + userName
					+ ", groups: " + groupList);
				}
			}

		} else {
			LOG.info("Performing Group search first");
			getGroups(sink, null);
            // Go through the userInfo map and update ranger admin.
            for (UserInfo userInfo : userGroupMap.values()) {
                String userName = getShortUserName(userInfo.getUserFullName());
                if (groupHierarchyLevels > 0) {
                    //System.out.println("Going through group hierarchy for nested group evaluation");
                    goUpGroupHierarchyLdap(userInfo.getGroupDNs(), groupHierarchyLevels - 1, userInfo);
                    //System.out.println("Completed group hierarchy computation");
                }
                if (userSearchEnabled) {
                    LOG.info("User search is enabled and hence computing user membership.");
                    getUsers(sink);
                } else {
                    LOG.info("User search is disabled and hence using the group member attribute for username" + userName);
                    List<String> groupList = userInfo.getGroups();
                    if (userNameCaseConversionFlag) {
                        if (userNameLowerCaseFlag) {
                            userName = userName.toLowerCase();
                        } else {
                            userName = userName.toUpperCase();
                        }
                    }

                    if (userNameRegExInst != null) {
                        userName = userNameRegExInst.transform(userName);
                    }

                    try {
                        sink.addOrUpdateUser(userName, groupList);
                    } catch (Throwable t) {
                        LOG.error("sink.addOrUpdateUser failed with exception: " + t.getMessage()
                                + ", for user: " + userName
                                + ", groups: " + groupList);
                    }
                }
            }
		}
	}

	private void getUsers(UserGroupSink sink) throws Throwable {
		UserInfo userInfo;
		NamingEnumeration<SearchResult> userSearchResultEnum = null;
		NamingEnumeration<SearchResult> groupSearchResultEnum = null;
		try {
			createLdapContext();
			int total;
			// Activate paged results
			if (pagedResultsEnabled)   {
				ldapContext.setRequestControls(new Control[]{
						new PagedResultsControl(pagedResultsSize, Control.NONCRITICAL) });
			}

			// When multiple OUs are configured, go through each OU as the user search base to search for users.
			for (String ou : userSearchBase) {
				byte[] cookie = null;
				int counter = 0;
				try {
					int paged = 0;
					do {
						userSearchResultEnum = ldapContext
								.search(ou, extendedUserSearchFilter, userSearchControls);

						while (userSearchResultEnum.hasMore()) {
							// searchResults contains all the user entries
							final SearchResult userEntry = userSearchResultEnum.next();

							if (userEntry == null)  {
								if (LOG.isInfoEnabled())  {
									LOG.info("userEntry null, skipping sync for the entry");
								}
								continue;
							}

							Attributes attributes = userEntry.getAttributes();
							if (attributes == null)  {
								if (LOG.isInfoEnabled())  {
									LOG.info("attributes  missing for entry " + userEntry.getNameInNamespace() +
											", skipping sync");
								}
								continue;
							}

							Attribute userNameAttr  = attributes.get(userNameAttribute);
							if (userNameAttr == null)  {
								if (LOG.isInfoEnabled())  {
									LOG.info(userNameAttribute + " missing for entry " + userEntry.getNameInNamespace() +
											", skipping sync");
								}
								continue;
							}

							String userName = (String) userNameAttr.get();

							if (userName == null || userName.trim().isEmpty())  {
								if (LOG.isInfoEnabled())  {
									LOG.info(userNameAttribute + " empty for entry " + userEntry.getNameInNamespace() +
											", skipping sync");
								}
								continue;
							}

							if (!groupSearchFirstEnabled) {
								userInfo = new UserInfo(userName, userEntry.getNameInNamespace());
								Set<String> groups = new HashSet<String>();

								// Get all the groups from the group name attribute of the user only when group search is not enabled.
								if (!groupSearchEnabled) {
									for (String useGroupNameAttribute : userGroupNameAttributeSet) {
										Attribute userGroupfAttribute = userEntry.getAttributes().get(useGroupNameAttribute);
										if (userGroupfAttribute != null) {
											NamingEnumeration<?> groupEnum = userGroupfAttribute.getAll();
											while (groupEnum.hasMore()) {
                                                String groupDN = (String) groupEnum.next();
                                                LOG.debug("Adding " + groupDN + " to " + userName);
                                                userInfo.addGroupDN(groupDN);
												String gName = getShortGroupName(groupDN);
												if (groupNameCaseConversionFlag) {
													if (groupNameLowerCaseFlag) {
														gName = gName.toLowerCase();
													} else {
														gName = gName.toUpperCase();
													}
												}
												if (groupNameRegExInst != null) {
													gName = groupNameRegExInst.transform(gName);
												}
												groups.add(gName);
											}
										}
									}
								}

								userInfo.addGroups(groups);

								//populate the userGroupMap with username, userInfo.
								//userInfo contains details of user that will be later used for
								//group search to compute group membership as well as to call sink.addOrUpdateUser()
								if (userGroupMap.containsKey(userName)) {
									LOG.warn("user object with username " + userName + " already exists and is replaced with the latest user object." );
								}
								userGroupMap.put(userName, userInfo);

								//List<String> groupList = new ArrayList<String>(groups);
								List<String> groupList = userInfo.getGroups();
								counter++;
								if (counter <= 2000) {
									if (LOG.isInfoEnabled()) {
										LOG.info("Updating user count: " + counter
												+ ", userName: " + userName + ", groupList: "
												+ groupList);
									}
									if ( counter == 2000 ) {
										LOG.info("===> 2000 user records have been synchronized so far. From now on, only a summary progress log will be written for every 100 users. To continue to see detailed log for every user, please enable Trace level logging. <===");
									}
								} else {
									if (LOG.isTraceEnabled()) {
										LOG.trace("Updating user count: " + counter
												+ ", userName: " + userName + ", groupList: "
												+ groupList);
									} else  {
										if ( counter % 100 == 0) {
											LOG.info("Synced " + counter + " users till now");
										}
									}
								}
							} else {
								// If the user from the search result is present in the usersList,
								// then update user name in the userInfo map with the value from the search result
								// and update ranger admin.
								String userFullName = (userEntry.getNameInNamespace()).toLowerCase();
								LOG.debug("Checking if the user " + userFullName + " is part of the retrieved groups");

								userInfo = userGroupMap.get(userFullName);
								if (userInfo == null) {
									userInfo = userGroupMap.get(userName.toLowerCase());
								}
								if (userInfo != null) {
									counter++;
									LOG.info("Updating username for " + userFullName + " with " + userName);
									userInfo.updateUserName(userName);
                                    List<String> groupList = userInfo.getGroups();
                                    if (userNameCaseConversionFlag) {
                                        if (userNameLowerCaseFlag) {
                                            userName = userName.toLowerCase();
                                        }
                                        else {
                                            userName = userName.toUpperCase();
                                        }
                                    }

                                    if (userNameRegExInst != null) {
                                        userName = userNameRegExInst.transform(userName);
                                    }

                                    try {
                                        sink.addOrUpdateUser(userName, groupList);
                                    } catch (Throwable t) {
                                        LOG.error("sink.addOrUpdateUser failed with exception: " + t.getMessage()
                                                + ", for user: " + userName
                                                + ", groups: " + groupList);
                                    }
								}
							}

						}

						// Examine the paged results control response
						Control[] controls = ldapContext.getResponseControls();
						if (controls != null) {
							for (Control control : controls) {
								if (control instanceof PagedResultsResponseControl) {
									PagedResultsResponseControl prrc =
											(PagedResultsResponseControl)control;
									total = prrc.getResultSize();
									if (total != 0) {
										LOG.debug("END-OF-PAGE total : " + total);
									} else {
										LOG.debug("END-OF-PAGE total : unknown");
									}
									cookie = prrc.getCookie();
								}
							}
						} else {
							LOG.debug("No controls were sent from the server");
						}
						// Re-activate paged results
						if (pagedResultsEnabled)   {
							LOG.debug(String.format("Fetched paged results round: %s", ++paged));
							ldapContext.setRequestControls(new Control[]{
									new PagedResultsControl(pagedResultsSize, cookie, Control.CRITICAL) });
						}
					} while (cookie != null);
					LOG.info("LDAPUserGroupBuilder.getUsers() completed with user count: "
							+ counter);
				} catch (Throwable t) {
					LOG.error("LDAPUserGroupBuilder.getUsers() failed with exception: " + t);
					LOG.info("LDAPUserGroupBuilder.getUsers() user count: "
							+ counter);
				}
			}

		} finally {
			if (userSearchResultEnum != null) {
				userSearchResultEnum.close();
			}
			if (groupSearchResultEnum != null) {
				groupSearchResultEnum.close();
			}
			closeLdapContext();
		}
	}

	private void getGroups(UserGroupSink sink, UserInfo userInfo) throws Throwable {
        //LOG.debug("getGroups(): for user " + userInfo.getUserName());
		NamingEnumeration<SearchResult> groupSearchResultEnum = null;
		try {
			createLdapContext();
			int total;
            // Activate paged results
			if (pagedResultsEnabled)   {
				ldapContext.setRequestControls(new Control[]{
						new PagedResultsControl(pagedResultsSize, Control.NONCRITICAL) });
			}
            for (String ou : groupSearchBase) {
				byte[] cookie = null;
				int counter = 0;
				try {
					int paged = 0;
					do {
						if (!groupSearchFirstEnabled) {
							if (userInfo == null) {
								// Should never reach this.
								LOG.error("No user information provided for group search!");
								return;
							}
							if (LOG.isDebugEnabled()) {
								LOG.debug("Searching for groups for user " + userInfo.getUserName() +
										" using filter " + String.format(extendedGroupSearchFilter, userInfo.getUserFullName(),
												userInfo.getUserName()));
							}
							groupSearchResultEnum = ldapContext
									.search(ou, extendedGroupSearchFilter,
											new Object[]{userInfo.getUserFullName(), userInfo.getUserName()},
											groupSearchControls);
						} else {
							// If group based search is enabled, then first retrieve all the groups based on the group configuration.
							groupSearchResultEnum = ldapContext
									.search(ou, extendedAllGroupsSearchFilter,
											groupSearchControls);
						}
						while (groupSearchResultEnum.hasMore()) {
							final SearchResult groupEntry = groupSearchResultEnum.next();
							if (groupEntry != null) {
								counter++;
								Attribute groupNameAttr = groupEntry.getAttributes().get(groupNameAttribute);
                                //System.out.println("getGroups(): Going through all groups");
								if (groupNameAttr == null) {
									if (LOG.isInfoEnabled())  {
										LOG.info(groupNameAttribute + " empty for entry " + groupEntry.getNameInNamespace() +
												", skipping sync");
									}
									continue;
								}
                                String groupDN = groupEntry.getNameInNamespace();
                                //System.out.println("getGroups(): groupDN = " + groupDN);
                                String gName = (String) groupNameAttr.get();
								if (groupNameCaseConversionFlag) {
									if (groupNameLowerCaseFlag) {
										gName = gName.toLowerCase();
									} else {
										gName = gName.toUpperCase();
									}
								}
								if (groupNameRegExInst != null) {
									gName = groupNameRegExInst.transform(gName);
								}
								if (!groupSearchFirstEnabled) {
									//computedGroups.add(gName);
									if (LOG.isInfoEnabled())  {
										LOG.info("computed groups for user: " + userInfo.getUserName() + ", groups: " + gName);
									}
                                    userInfo.addGroupDN(groupDN);
                                    userInfo.addGroup(gName);
								} else {
									// If group based search is enabled, then
									// update the group name to ranger admin
									// check for group members and populate userInfo object with user's full name and group mapping
									Attribute groupMemberAttr = groupEntry.getAttributes().get(groupMemberAttributeName);
									LOG.debug("Update Ranger admin with " + gName);
									sink.addOrUpdateGroup(gName);
									int userCount = 0;
									if (groupMemberAttr == null || groupMemberAttr.size() <= 0) {
										LOG.info("No members available for " + gName);
										continue;
									}
									NamingEnumeration<?> userEnum = groupMemberAttr.getAll();
									while (userEnum.hasMore()) {
										String originalUserFullName = (String) userEnum.next();
										if (originalUserFullName == null || originalUserFullName.trim().isEmpty()) {
											continue;
										}
										String userFullName = originalUserFullName.toLowerCase();
										userCount++;
										if (!userGroupMap.containsKey(userFullName)) {
											userInfo = new UserInfo(userFullName, originalUserFullName); // Preserving the original full name for later
											userGroupMap.put(userFullName, userInfo);
										} else {
											userInfo = userGroupMap.get(userFullName);
                                        }
                                        LOG.info("Adding " + gName + " to user " + userInfo.getUserFullName());
                                        userInfo.addGroup(gName);
                                        userInfo.addGroupDN(groupDN);
									}
									LOG.info("No. of members in the group " + gName + " = " + userCount);
								}
							}
						}
						// Examine the paged results control response
						Control[] controls = ldapContext.getResponseControls();
						if (controls != null) {
							for (Control control : controls) {
								if (control instanceof PagedResultsResponseControl) {
									PagedResultsResponseControl prrc =
											(PagedResultsResponseControl)control;
									total = prrc.getResultSize();
									if (total != 0) {
										LOG.debug("END-OF-PAGE total : " + total);
									} else {
										LOG.debug("END-OF-PAGE total : unknown");
									}
									cookie = prrc.getCookie();
								}
							}
						} else {
							LOG.debug("No controls were sent from the server");
						}
						// Re-activate paged results
						if (pagedResultsEnabled)   {
							LOG.debug(String.format("Fetched paged results round: %s", ++paged));
							ldapContext.setRequestControls(new Control[]{
									new PagedResultsControl(pagedResultsSize, cookie, Control.CRITICAL) });
						}
					} while (cookie != null);
					LOG.info("LDAPUserGroupBuilder.getGroups() completed with group count: "
							+ counter);
				} catch (Throwable t) {
					LOG.error("LDAPUserGroupBuilder.getGroups() failed with exception: " + t);
					LOG.info("LDAPUserGroupBuilder.getGroups() group count: "
							+ counter);
				}
			}

		} finally {
			if (groupSearchResultEnum != null) {
				groupSearchResultEnum.close();
			}
			closeLdapContext();
		}
	}


	private static String getShortGroupName(String longGroupName) throws InvalidNameException {
		if (longGroupName == null) {
			return null;
		}
		StringTokenizer stc = new StringTokenizer(longGroupName, ",");
		String firstToken = stc.nextToken();
		StringTokenizer ste = new StringTokenizer(firstToken, "=");
		String groupName =  ste.nextToken();
		if (ste.hasMoreTokens()) {
			groupName = ste.nextToken();
		}
		groupName = groupName.trim();
		LOG.info("longGroupName: " + longGroupName + ", groupName: " + groupName);
		return groupName;
	}

	private static String getShortUserName(String longUserName) throws InvalidNameException {
		if (longUserName == null) {
			return null;
		}
		StringTokenizer stc = new StringTokenizer(longUserName, ",");
		String firstToken = stc.nextToken();
		StringTokenizer ste = new StringTokenizer(firstToken, "=");
		String userName =  ste.nextToken();
		if (ste.hasMoreTokens()) {
			userName = ste.nextToken();
		}
		userName = userName.trim();
		LOG.info("longUserName: " + longUserName + ", userName: " + userName);
		return userName;
	}

	private void goUpGroupHierarchyLdap(Set<String> groupDNs, int groupHierarchyLevels, UserInfo userInfo) throws Throwable {
        LOG.debug("goUpGroupHierarchyLdap(): Incoming groups " + groupDNs);
		if (groupHierarchyLevels <= 0 || groupDNs.isEmpty()) {
			return;
		}
		Set<String> nextLevelGroups = new HashSet<String>();

		NamingEnumeration<SearchResult> groupSearchResultEnum = null;
		try {
			createLdapContext();
			int total;
			// Activate paged results
			if (pagedResultsEnabled)   {
				ldapContext.setRequestControls(new Control[]{
						new PagedResultsControl(pagedResultsSize, Control.NONCRITICAL) });
			}
			String groupFilter = "(&(objectclass=" + groupObjectClass + ")";
            if (groupSearchFilter != null && !groupSearchFilter.trim().isEmpty()) {
                String customFilter = groupSearchFilter.trim();
                if (!customFilter.startsWith("(")) {
                    customFilter = "(" + customFilter + ")";
                }
                groupFilter += customFilter + "(|";
            }
			StringBuilder filter = new StringBuilder();

			for (String groupDN : groupDNs) {
				filter.append("(").append(groupMemberAttributeName).append("=")
						.append(groupDN).append(")");
			}
			filter.append("))");
            groupFilter += filter;

			LOG.debug("extendedAllGroupsSearchFilter = " + groupFilter);
			for (String ou : groupSearchBase) {
				byte[] cookie = null;
				int counter = 0;
				try {
					do {
						groupSearchResultEnum = ldapContext
									.search(ou, groupFilter,
											groupSearchControls);
                        //System.out.println("goUpGroupHierarchyLdap(): Going through the sub groups");
						while (groupSearchResultEnum.hasMore()) {
							final SearchResult groupEntry = groupSearchResultEnum.next();
							if (groupEntry == null) {
								if (LOG.isInfoEnabled())  {
									LOG.info("groupEntry null, skipping sync for the entry");
								}
								continue;
							}
							counter++;
							Attribute groupNameAttr = groupEntry.getAttributes().get(groupNameAttribute);
							if (groupNameAttr == null) {
								if (LOG.isInfoEnabled())  {
									LOG.info(groupNameAttribute + " empty for entry " + groupEntry.getNameInNamespace() +
											", skipping sync");
								}
								continue;
							}
                            String groupDN = groupEntry.getNameInNamespace();
                            //System.out.println("goUpGroupHierarchyLdap(): next Level Group DN = " + groupDN);
							nextLevelGroups.add(groupDN);
							String gName = (String) groupNameAttr.get();
							if (groupNameCaseConversionFlag) {
								if (groupNameLowerCaseFlag) {
									gName = gName.toLowerCase();
								} else {
									gName = gName.toUpperCase();
								}
							}
							if (groupNameRegExInst != null) {
								gName = groupNameRegExInst.transform(gName);
							}
							userInfo.addGroup(gName);
						}
						// Examine the paged results control response
						Control[] controls = ldapContext.getResponseControls();
						if (controls != null) {
							for (Control control : controls) {
								if (control instanceof PagedResultsResponseControl) {
									PagedResultsResponseControl prrc =
											(PagedResultsResponseControl)control;
									total = prrc.getResultSize();
									if (total != 0) {
										LOG.debug("END-OF-PAGE total : " + total);
									} else {
										LOG.debug("END-OF-PAGE total : unknown");
									}
									cookie = prrc.getCookie();
								}
							}
						} else {
							LOG.debug("No controls were sent from the server");
						}
						// Re-activate paged results
						if (pagedResultsEnabled)   {
							ldapContext.setRequestControls(new Control[]{
									new PagedResultsControl(PAGE_SIZE, cookie, Control.CRITICAL) });
						}
					} while (cookie != null);
					LOG.info("LdapUserGroupBuilder.goUpGroupHierarchyLdap() completed with group count: "
							+ counter);
				} catch (RuntimeException re) {
					LOG.error("LdapUserGroupBuilder.goUpGroupHierarchyLdap() failed with runtime exception: ", re);
					throw re;
				} catch (Exception t) {
					LOG.error("LdapUserGroupBuilder.goUpGroupHierarchyLdap() failed with exception: ", t);
					LOG.info("LdapUserGroupBuilder.goUpGroupHierarchyLdap() group count: "
							+ counter);
				}
			}

		} catch (RuntimeException re) {
			LOG.error("LdapUserGroupBuilder.goUpGroupHierarchyLdap() failed with exception: ", re);
			throw re;
		} finally {
			if (groupSearchResultEnum != null) {
				groupSearchResultEnum.close();
			}
			closeLdapContext();
		}
		goUpGroupHierarchyLdap(nextLevelGroups, groupHierarchyLevels - 1, userInfo);
	}

	private void getRootDN() throws Throwable {
		NamingEnumeration groupSearchResultEnum = null;
		SearchControls sc1 = new SearchControls();
		sc1.setSearchScope(SearchControls.OBJECT_SCOPE);
		sc1.setReturningAttributes(new String[]{"namingContexts"});
		try {
			createLdapContext();
			groupSearchResultEnum = ldapContext
					.search("", "objectclass=*", sc1);
			//System.out.println("goUpGroupHierarchyLdap(): Going through the sub groups");
			while (groupSearchResultEnum.hasMore()) {
				SearchResult result1 = (SearchResult) groupSearchResultEnum.next();

				Attributes attrs = result1.getAttributes();
				Attribute attr = attrs.get("namingContexts");
				LOG.debug("namingContexts = " + attr);
				groupSearchBase = new String[] {attr.get(0).toString()};
				LOG.info("RootDN = " + Arrays.toString(groupSearchBase));
			}
		} catch (RuntimeException re) {
			throw re;
		} finally {
			if (groupSearchResultEnum != null) {
				groupSearchResultEnum.close();
			}
			closeLdapContext();
		}
	}
}

class UserInfo {
	private String userName;
	private String userFullName;
	private Set<String> groupList;
    private Set<String> groupDNList;

	public UserInfo(String userName, String userFullName) {
		this.userName = userName;
		this.userFullName = userFullName;
		this.groupList = new HashSet<String>();
        this.groupDNList = new HashSet<String>();
	}

	public void updateUserName(String userName) {
		this.userName = userName;
	}

	public String getUserName() {
		return userName;
	}
	public String getUserFullName() {
		return userFullName;
	}
	public void addGroups(Set<String> groups) {
		groupList.addAll(groups);
	}
	public void addGroup(String group) {
		groupList.add(group);
	}
	public List<String> getGroups() {
		return (new ArrayList<String>(groupList));
	}

    public void addGroupDNs(Set<String> groupDNs) {
        groupDNList.addAll(groupDNs);
    }
    public void addGroupDN(String groupDN) {
        groupDNList.add(groupDN);
    }
    public Set<String> getGroupDNs() {
        return (groupDNList);
    }
}
