public User importLDAPUserByScreenName(long companyId, String screenName) throws Exception {

    long ldapServerId = PortalLDAPUtil.getLdapServerId(companyId, screenName, StringPool.BLANK);

    SearchResult result =
        (SearchResult)
            PortalLDAPUtil.getUser(ldapServerId, companyId, screenName, StringPool.BLANK);

    if (result == null) {
      if (_log.isWarnEnabled()) {
        _log.warn("No user was found in LDAP with screenName " + screenName);
      }

      return null;
    }

    LdapContext ldapContext = PortalLDAPUtil.getContext(ldapServerId, companyId);

    String fullUserDN = PortalLDAPUtil.getNameInNamespace(ldapServerId, companyId, result);

    Attributes attributes =
        PortalLDAPUtil.getUserAttributes(ldapServerId, companyId, ldapContext, fullUserDN);

    User user = importLDAPUser(ldapServerId, companyId, ldapContext, attributes, StringPool.BLANK);

    ldapContext.close();

    return user;
  }
  protected Attribute getUsers(
      long ldapServerId,
      long companyId,
      LdapContext ldapContext,
      Attributes attributes,
      UserGroup userGroup,
      Properties groupMappings)
      throws Exception {

    Attribute attribute = attributes.get(groupMappings.getProperty("user"));

    if (attribute == null) {
      return null;
    }

    String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);

    String baseDN = PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_BASE_DN + postfix);

    StringBundler sb = new StringBundler(7);

    sb.append("(&");
    sb.append(
        PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER + postfix));
    sb.append("(");
    sb.append(groupMappings.getProperty("groupName"));
    sb.append("=");
    sb.append(escapeValue(userGroup.getName()));
    sb.append("))");

    return PortalLDAPUtil.getMultivaluedAttribute(
        companyId, ldapContext, baseDN, sb.toString(), attribute);
  }
  public void importFromLDAP(long ldapServerId, long companyId) throws Exception {

    if (!LDAPSettingsUtil.isImportEnabled(companyId)) {
      return;
    }

    LdapContext ldapContext = PortalLDAPUtil.getContext(ldapServerId, companyId);

    if (ldapContext == null) {
      return;
    }

    try {
      Properties userMappings = LDAPSettingsUtil.getUserMappings(ldapServerId, companyId);
      Properties userExpandoMappings =
          LDAPSettingsUtil.getUserExpandoMappings(ldapServerId, companyId);
      Properties contactMappings = LDAPSettingsUtil.getContactMappings(ldapServerId, companyId);
      Properties contactExpandoMappings =
          LDAPSettingsUtil.getContactExpandoMappings(ldapServerId, companyId);
      Properties groupMappings = LDAPSettingsUtil.getGroupMappings(ldapServerId, companyId);

      String importMethod = PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_IMPORT_METHOD);

      if (importMethod.equals(_IMPORT_BY_GROUP)) {
        importFromLDAPByGroup(
            ldapServerId,
            companyId,
            ldapContext,
            userMappings,
            userExpandoMappings,
            contactMappings,
            contactExpandoMappings,
            groupMappings);
      } else if (importMethod.equals(_IMPORT_BY_USER)) {
        importFromLDAPByUser(
            ldapServerId,
            companyId,
            ldapContext,
            userMappings,
            userExpandoMappings,
            contactMappings,
            contactExpandoMappings,
            groupMappings);
      }
    } catch (Exception e) {
      _log.error("Error importing LDAP users and groups", e);
    } finally {
      if (ldapContext != null) {
        ldapContext.close();
      }
    }
  }
  protected void importGroups(
      long ldapServerId,
      long companyId,
      LdapContext ldapContext,
      Attributes attributes,
      User user,
      Properties userMappings,
      Properties groupMappings)
      throws Exception {

    List<Long> newUserGroupIds = new ArrayList<Long>();

    if (PrefsPropsUtil.getBoolean(companyId, PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER_ENABLED)) {

      String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);

      String baseDN = PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_BASE_DN + postfix);

      Binding binding =
          PortalLDAPUtil.getUser(
              ldapServerId, companyId, user.getScreenName(), user.getEmailAddress());

      String fullUserDN = PortalLDAPUtil.getNameInNamespace(ldapServerId, companyId, binding);

      StringBundler sb = new StringBundler(9);

      sb.append(StringPool.OPEN_PARENTHESIS);
      sb.append(StringPool.AMPERSAND);
      sb.append(
          PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER + postfix));
      sb.append(StringPool.OPEN_PARENTHESIS);
      sb.append(groupMappings.getProperty("user"));
      sb.append(StringPool.EQUAL);
      sb.append(escapeValue(fullUserDN));
      sb.append(StringPool.CLOSE_PARENTHESIS);
      sb.append(StringPool.CLOSE_PARENTHESIS);

      byte[] cookie = new byte[0];

      while (cookie != null) {
        List<SearchResult> searchResults = new ArrayList<SearchResult>();

        String groupMappingsGroupName =
            GetterUtil.getString(groupMappings.getProperty("groupName")).toLowerCase();

        cookie =
            PortalLDAPUtil.searchLDAP(
                companyId,
                ldapContext,
                cookie,
                0,
                baseDN,
                sb.toString(),
                new String[] {groupMappingsGroupName},
                searchResults);

        for (SearchResult searchResult : searchResults) {
          String fullGroupDN =
              PortalLDAPUtil.getNameInNamespace(ldapServerId, companyId, searchResult);

          newUserGroupIds =
              importGroup(
                  ldapServerId,
                  companyId,
                  ldapContext,
                  fullGroupDN,
                  user,
                  groupMappings,
                  newUserGroupIds);
        }
      }
    } else {
      String userMappingsGroup = userMappings.getProperty("group");

      if (Validator.isNull(userMappingsGroup)) {
        return;
      }

      Attribute userGroupAttribute = attributes.get(userMappingsGroup);

      if (userGroupAttribute == null) {
        return;
      }

      for (int i = 0; i < userGroupAttribute.size(); i++) {
        String fullGroupDN = (String) userGroupAttribute.get(i);

        newUserGroupIds =
            importGroup(
                ldapServerId,
                companyId,
                ldapContext,
                fullGroupDN,
                user,
                groupMappings,
                newUserGroupIds);
      }
    }

    addUserGroupsNotAddedByLDAPImport(user.getUserId(), newUserGroupIds);

    for (long newUserGroupId : newUserGroupIds) {
      UserLocalServiceUtil.addUserGroupUsers(newUserGroupId, new long[] {user.getUserId()});
    }

    List<UserGroup> userUserGroups = UserGroupLocalServiceUtil.getUserUserGroups(user.getUserId());

    for (UserGroup userGroup : userUserGroups) {
      if (!newUserGroupIds.contains(userGroup.getUserGroupId())) {
        UserLocalServiceUtil.deleteUserGroupUser(userGroup.getUserGroupId(), user.getUserId());
      }
    }
  }
  protected List<Long> importGroup(
      long ldapServerId,
      long companyId,
      LdapContext ldapContext,
      String fullGroupDN,
      User user,
      Properties groupMappings,
      List<Long> newUserGroupIds)
      throws Exception {

    String userGroupIdKey = null;

    Long userGroupId = null;

    if (PropsValues.LDAP_IMPORT_GROUP_CACHE_ENABLED) {
      StringBundler sb = new StringBundler(5);

      sb.append(ldapServerId);
      sb.append(StringPool.UNDERLINE);
      sb.append(companyId);
      sb.append(StringPool.UNDERLINE);
      sb.append(fullGroupDN);

      userGroupIdKey = sb.toString();

      userGroupId = (Long) _portalCache.get(userGroupIdKey);
    }

    if (userGroupId != null) {
      if (_log.isDebugEnabled()) {
        _log.debug("Skipping reimport of full group DN " + fullGroupDN);
      }
    } else {
      if (_log.isDebugEnabled()) {
        _log.debug("Importing full group DN " + fullGroupDN);
      }

      Attributes groupAttributes = null;

      try {
        groupAttributes =
            PortalLDAPUtil.getGroupAttributes(ldapServerId, companyId, ldapContext, fullGroupDN);
      } catch (NameNotFoundException nnfe) {
        _log.error("LDAP group not found with full group DN " + fullGroupDN, nnfe);
      }

      UserGroup userGroup = importUserGroup(companyId, groupAttributes, groupMappings);

      userGroupId = userGroup.getUserGroupId();

      if (PropsValues.LDAP_IMPORT_GROUP_CACHE_ENABLED) {
        _portalCache.put(userGroupIdKey, userGroupId);
      }
    }

    if (userGroupId != null) {
      if (_log.isDebugEnabled()) {
        _log.debug("Adding " + user.getUserId() + " to group " + userGroupId);
      }

      newUserGroupIds.add(userGroupId);
    }

    return newUserGroupIds;
  }
  protected void importFromLDAPByUser(
      long ldapServerId,
      long companyId,
      LdapContext ldapContext,
      Properties userMappings,
      Properties userExpandoMappings,
      Properties contactMappings,
      Properties contactExpandoMappings,
      Properties groupMappings)
      throws Exception {

    byte[] cookie = new byte[0];

    while (cookie != null) {
      List<SearchResult> searchResults = new ArrayList<SearchResult>();

      String userMappingsScreenName =
          GetterUtil.getString(userMappings.getProperty("screenName")).toLowerCase();

      cookie =
          PortalLDAPUtil.getUsers(
              ldapServerId,
              companyId,
              ldapContext,
              cookie,
              0,
              new String[] {userMappingsScreenName},
              searchResults);

      for (SearchResult searchResult : searchResults) {
        try {
          Attributes userAttributes =
              PortalLDAPUtil.getUserAttributes(
                  ldapServerId,
                  companyId,
                  ldapContext,
                  PortalLDAPUtil.getNameInNamespace(ldapServerId, companyId, searchResult));

          User user =
              importUser(
                  companyId,
                  userAttributes,
                  userMappings,
                  userExpandoMappings,
                  contactMappings,
                  contactExpandoMappings,
                  StringPool.BLANK);

          importGroups(
              ldapServerId,
              companyId,
              ldapContext,
              userAttributes,
              user,
              userMappings,
              groupMappings);
        } catch (Exception e) {
          _log.error("Unable to import user " + searchResult, e);
        }
      }
    }
  }
  protected void importFromLDAPByGroup(
      long ldapServerId,
      long companyId,
      LdapContext ldapContext,
      Properties userMappings,
      Properties userExpandoMappings,
      Properties contactMappings,
      Properties contactExpandoMappings,
      Properties groupMappings)
      throws Exception {

    byte[] cookie = new byte[0];

    while (cookie != null) {
      List<SearchResult> searchResults = new ArrayList<SearchResult>();

      String groupMappingsGroupName =
          GetterUtil.getString(groupMappings.getProperty("groupName")).toLowerCase();

      cookie =
          PortalLDAPUtil.getGroups(
              ldapServerId,
              companyId,
              ldapContext,
              cookie,
              0,
              new String[] {groupMappingsGroupName},
              searchResults);

      for (SearchResult searchResult : searchResults) {
        try {
          Attributes attributes =
              PortalLDAPUtil.getGroupAttributes(
                  ldapServerId,
                  companyId,
                  ldapContext,
                  PortalLDAPUtil.getNameInNamespace(ldapServerId, companyId, searchResult),
                  true);

          UserGroup userGroup = importUserGroup(companyId, attributes, groupMappings);

          Attribute usersAttribute =
              getUsers(ldapServerId, companyId, ldapContext, attributes, userGroup, groupMappings);

          if (usersAttribute == null) {
            if (_log.isInfoEnabled()) {
              _log.info("No users found in " + userGroup.getName());
            }

            continue;
          }

          importUsers(
              ldapServerId,
              companyId,
              ldapContext,
              userMappings,
              userExpandoMappings,
              contactMappings,
              contactExpandoMappings,
              userGroup.getUserGroupId(),
              usersAttribute);
        } catch (Exception e) {
          _log.error("Unable to import group " + searchResult, e);
        }
      }
    }
  }
  public User importLDAPUser(
      long ldapServerId, long companyId, String emailAddress, String screenName) throws Exception {

    LdapContext ldapContext = null;

    NamingEnumeration<SearchResult> enu = null;

    try {
      String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);

      String baseDN = PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_BASE_DN + postfix);

      ldapContext = PortalLDAPUtil.getContext(ldapServerId, companyId);

      if (ldapContext == null) {
        throw new SystemException("Failed to bind to the LDAP server");
      }

      String filter =
          PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_AUTH_SEARCH_FILTER + postfix);

      if (_log.isDebugEnabled()) {
        _log.debug("Search filter before transformation " + filter);
      }

      filter =
          StringUtil.replace(
              filter,
              new String[] {"@company_id@", "@email_address@", "@screen_name@"},
              new String[] {String.valueOf(companyId), emailAddress, screenName});

      if (_log.isDebugEnabled()) {
        _log.debug("Search filter after transformation " + filter);
      }

      Properties userMappings = LDAPSettingsUtil.getUserMappings(ldapServerId, companyId);

      String userMappingsScreenName =
          GetterUtil.getString(userMappings.getProperty("screenName")).toLowerCase();

      SearchControls searchControls =
          new SearchControls(
              SearchControls.SUBTREE_SCOPE,
              1,
              0,
              new String[] {userMappingsScreenName},
              false,
              false);

      enu = ldapContext.search(baseDN, filter, searchControls);

      if (enu.hasMoreElements()) {
        if (_log.isDebugEnabled()) {
          _log.debug("Search filter returned at least one result");
        }

        Binding binding = enu.nextElement();

        Attributes attributes =
            PortalLDAPUtil.getUserAttributes(
                ldapServerId,
                companyId,
                ldapContext,
                PortalLDAPUtil.getNameInNamespace(ldapServerId, companyId, binding));

        return importLDAPUser(ldapServerId, companyId, ldapContext, attributes, StringPool.BLANK);
      } else {
        return null;
      }
    } catch (Exception e) {
      if (_log.isWarnEnabled()) {
        _log.warn("Problem accessing LDAP server " + e.getMessage());
      }

      if (_log.isDebugEnabled()) {
        _log.debug(e, e);
      }

      throw new SystemException("Problem accessing LDAP server " + e.getMessage());
    } finally {
      if (enu != null) {
        enu.close();
      }

      if (ldapContext != null) {
        ldapContext.close();
      }
    }
  }
  protected void importUsers(
      long ldapServerId,
      long companyId,
      LdapContext ldapContext,
      Properties userMappings,
      Properties userExpandoMappings,
      Properties contactMappings,
      Properties contactExpandoMappings,
      long userGroupId,
      Attribute attribute)
      throws Exception {

    List<Long> newUserIds = new ArrayList<Long>(attribute.size());

    for (int i = 0; i < attribute.size(); i++) {
      String fullUserDN = (String) attribute.get(i);

      Attributes userAttributes = null;

      try {
        userAttributes =
            PortalLDAPUtil.getUserAttributes(ldapServerId, companyId, ldapContext, fullUserDN);
      } catch (NameNotFoundException nnfe) {
        _log.error("LDAP user not found with fullUserDN " + fullUserDN, nnfe);

        continue;
      }

      try {
        User user =
            importUser(
                companyId,
                userAttributes,
                userMappings,
                userExpandoMappings,
                contactMappings,
                contactExpandoMappings,
                StringPool.BLANK);

        if (user != null) {
          if (_log.isDebugEnabled()) {
            _log.debug("Adding " + user.getUserId() + " to group " + userGroupId);
          }

          UserLocalServiceUtil.addUserGroupUsers(userGroupId, new long[] {user.getUserId()});

          newUserIds.add(user.getUserId());
        }
      } catch (Exception e) {
        _log.error("Unable to load user " + userAttributes, e);
      }
    }

    List<User> userGroupUsers = UserLocalServiceUtil.getUserGroupUsers(userGroupId);

    for (User user : userGroupUsers) {
      if (!newUserIds.contains(user.getUserId())) {
        UserLocalServiceUtil.deleteUserGroupUser(userGroupId, user.getUserId());
      }
    }
  }