@BeforeClass
  public static void setUpClass() throws Exception {
    RegistryUtil.setRegistry(new BasicRegistryImpl());

    MultiVMPoolUtil multiVMPoolUtil = new MultiVMPoolUtil();

    MultiVMPoolImpl multiVMPoolImpl = new MultiVMPoolImpl();

    multiVMPoolImpl.setPortalCacheManager(
        MemoryPortalCacheManager.<Serializable, Serializable>createMemoryPortalCacheManager(
            "multi.vm.pool"));

    multiVMPoolUtil.setMultiVMPool(multiVMPoolImpl);

    SingleVMPoolUtil singleVMPoolUtil = new SingleVMPoolUtil();

    SingleVMPoolImpl singleVMPoolImpl = new SingleVMPoolImpl();

    singleVMPoolImpl.setPortalCacheManager(
        MemoryPortalCacheManager.createMemoryPortalCacheManager("single.vm.pool"));

    singleVMPoolUtil.setSingleVMPool(singleVMPoolImpl);

    _templateResourceLoader = new MockTemplateResourceLoader();

    _templateResourceLoader.activate(Collections.<String, Object>emptyMap());

    Registry registry = RegistryUtil.getRegistry();

    _serviceRegistration =
        registry.registerService(TemplateResourceLoader.class, _templateResourceLoader);
  }
/** @author Eduardo Lundgren */
public class JavaScriptBundleUtil {

  public static void clearCache() {
    _portalCache.removeAll();
  }

  public static String[] getFileNames(String bundleId) {
    String[] fileNames = (String[]) _portalCache.get(bundleId);

    if (fileNames == null) {
      List<String> fileNamesList = new ArrayList<String>();

      List<String> dependencies = _getDependencies(bundleId, new UniqueList<String>());

      for (String dependency : dependencies) {
        String[] dependencyFileNames = PropsUtil.getArray(dependency);

        for (String dependencyFileName : dependencyFileNames) {
          fileNamesList.add(dependencyFileName);
        }
      }

      fileNames = fileNamesList.toArray(new String[fileNamesList.size()]);

      _portalCache.put(bundleId, fileNames);
    }

    return fileNames;
  }

  private static List<String> _getDependencies(String bundleId, List<String> dependencies) {

    if (!ArrayUtil.contains(PropsValues.JAVASCRIPT_BUNDLE_IDS, bundleId)) {
      return dependencies;
    }

    String[] bundleDependencies =
        PropsUtil.getArray(PropsKeys.JAVASCRIPT_BUNDLE_DEPENDENCIES, new Filter(bundleId));

    for (String bundleDependency : bundleDependencies) {
      String[] bundleDependencyDependencies =
          PropsUtil.getArray(
              PropsKeys.JAVASCRIPT_BUNDLE_DEPENDENCIES, new Filter(bundleDependency));

      if (!ArrayUtil.contains(bundleDependencyDependencies, bundleId)) {
        _getDependencies(bundleDependency, dependencies);
      }

      dependencies.add(bundleDependency);
    }

    dependencies.add(bundleId);

    return dependencies;
  }

  private static final String _CACHE_NAME = JavaScriptBundleUtil.class.getName();

  private static PortalCache _portalCache = SingleVMPoolUtil.getCache(_CACHE_NAME);
}
  @Before
  public void setUp() {
    SingleVMPoolUtil singleVMPoolUtil = new SingleVMPoolUtil();

    SingleVMPoolImpl singleVMPoolImpl = new SingleVMPoolImpl();

    singleVMPoolImpl.setPortalCacheManager(
        MemoryPortalCacheManager.createMemoryPortalCacheManager(
            PortletPreferencesFactoryImplUnitTest.class.getName()));

    singleVMPoolUtil.setSingleVMPool(singleVMPoolImpl);

    PortletPreferencesFactoryUtil portletPreferencesFactoryUtil =
        new PortletPreferencesFactoryUtil();

    portletPreferencesFactoryUtil.setPortletPreferencesFactory(new PortletPreferencesFactoryImpl());

    _layout.setCompanyId(RandomTestUtil.randomLong());
    _layout.setPlid(RandomTestUtil.randomLong());
    _layout.setPrivateLayout(true);
  }
/**
 * @author Michael C. Han
 * @author Brian Wing Shun Chan
 * @author Wesley Gong
 * @author Hugo Huijser
 */
public class PortalLDAPImporterImpl implements PortalLDAPImporter {

  public void importFromLDAP() throws Exception {
    List<Company> companies = CompanyLocalServiceUtil.getCompanies(false);

    for (Company company : companies) {
      importFromLDAP(company.getCompanyId());
    }
  }

  public void importFromLDAP(long companyId) throws Exception {
    if (!LDAPSettingsUtil.isImportEnabled(companyId)) {
      return;
    }

    long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);

    if (LockLocalServiceUtil.hasLock(
        defaultUserId, PortalLDAPImporterUtil.class.getName(), companyId)) {

      if (_log.isDebugEnabled()) {
        _log.debug(
            "Skipping LDAP import for company "
                + companyId
                + "because another LDAP import is in process");
      }

      return;
    }

    LockLocalServiceUtil.lock(
        defaultUserId,
        PortalLDAPImporterUtil.class.getName(),
        companyId,
        PortalLDAPImporterImpl.class.getName(),
        false,
        PropsValues.LDAP_IMPORT_LOCK_EXPIRATION_TIME);

    long threadLocalCompanyId = CompanyThreadLocal.getCompanyId();

    try {
      if (threadLocalCompanyId == CompanyConstants.SYSTEM) {
        CompanyThreadLocal.setCompanyId(companyId);
      }

      long[] ldapServerIds =
          StringUtil.split(PrefsPropsUtil.getString(companyId, "ldap.server.ids"), 0L);

      for (long ldapServerId : ldapServerIds) {
        importFromLDAP(ldapServerId, companyId);
      }

      for (int ldapServerId = 0; ; ldapServerId++) {
        String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);

        String providerUrl =
            PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_BASE_PROVIDER_URL + postfix);

        if (Validator.isNull(providerUrl)) {
          break;
        }

        importFromLDAP(ldapServerId, companyId);
      }
    } finally {
      LockLocalServiceUtil.unlock(PortalLDAPImporterUtil.class.getName(), companyId);

      CompanyThreadLocal.setCompanyId(threadLocalCompanyId);
    }
  }

  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();
      }
    }
  }

  public User importLDAPUser(
      long ldapServerId,
      long companyId,
      LdapContext ldapContext,
      Attributes attributes,
      String password)
      throws Exception {

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

    User user =
        importUser(
            companyId,
            attributes,
            userMappings,
            userExpandoMappings,
            contactMappings,
            contactExpandoMappings,
            password);

    Properties groupMappings = LDAPSettingsUtil.getGroupMappings(ldapServerId, companyId);

    importGroups(
        ldapServerId, companyId, ldapContext, attributes, user, userMappings, groupMappings);

    return user;
  }

  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();
      }
    }
  }

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

    long[] ldapServerIds =
        StringUtil.split(PrefsPropsUtil.getString(companyId, "ldap.server.ids"), 0L);

    for (long ldapServerId : ldapServerIds) {
      User user = importLDAPUser(ldapServerId, companyId, emailAddress, screenName);

      if (user != null) {
        return user;
      }
    }

    for (int ldapServerId = 0; ; ldapServerId++) {
      String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);

      String providerUrl =
          PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_BASE_PROVIDER_URL + postfix);

      if (Validator.isNull(providerUrl)) {
        break;
      }

      User user = importLDAPUser(ldapServerId, companyId, emailAddress, screenName);

      if (user != null) {
        return user;
      }
    }

    if (_log.isDebugEnabled()) {
      if (Validator.isNotNull(emailAddress)) {
        _log.debug(
            "User with the email address " + emailAddress + " was not found in any LDAP servers");
      } else {
        _log.debug(
            "User with the screen name " + screenName + " was not found in any LDAP servers");
      }
    }

    return null;
  }

  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;
  }

  public void setLDAPToPortalConverter(LDAPToPortalConverter ldapToPortalConverter) {

    _ldapToPortalConverter = ldapToPortalConverter;
  }

  protected void addRole(long companyId, LDAPGroup ldapGroup, UserGroup userGroup)
      throws Exception {

    if (!PropsValues.LDAP_IMPORT_CREATE_ROLE_PER_GROUP) {
      return;
    }

    Role role = null;

    try {
      role = RoleLocalServiceUtil.getRole(companyId, ldapGroup.getGroupName());
    } catch (NoSuchRoleException nsre) {
      User defaultUser = UserLocalServiceUtil.getDefaultUser(companyId);

      Map<Locale, String> descriptionMap = new HashMap<Locale, String>();

      descriptionMap.put(LocaleUtil.getDefault(), "Autogenerated role from LDAP import");

      role =
          RoleLocalServiceUtil.addRole(
              defaultUser.getUserId(),
              companyId,
              ldapGroup.getGroupName(),
              null,
              descriptionMap,
              RoleConstants.TYPE_REGULAR);
    }

    Group group = userGroup.getGroup();

    if (GroupLocalServiceUtil.hasRoleGroup(role.getRoleId(), group.getGroupId())) {

      return;
    }

    GroupLocalServiceUtil.addRoleGroups(role.getRoleId(), new long[] {group.getGroupId()});
  }

  protected User addUser(long companyId, LDAPUser ldapUser, String password) throws Exception {

    if (_log.isDebugEnabled()) {
      _log.debug("Adding user " + ldapUser.getEmailAddress());
    }

    boolean autoPassword = ldapUser.isAutoPassword();

    if (!PropsValues.LDAP_IMPORT_USER_PASSWORD_ENABLED) {
      autoPassword = PropsValues.LDAP_IMPORT_USER_PASSWORD_AUTOGENERATED;

      if (!autoPassword) {
        String defaultPassword = PropsValues.LDAP_IMPORT_USER_PASSWORD_DEFAULT;

        if (defaultPassword.equalsIgnoreCase(_USER_PASSWORD_SCREEN_NAME)) {

          defaultPassword = ldapUser.getScreenName();
        }

        password = defaultPassword;
      }
    }

    Calendar birthdayCal = CalendarFactoryUtil.getCalendar();

    birthdayCal.setTime(ldapUser.getBirthday());

    int birthdayMonth = birthdayCal.get(Calendar.MONTH);
    int birthdayDay = birthdayCal.get(Calendar.DAY_OF_MONTH);
    int birthdayYear = birthdayCal.get(Calendar.YEAR);

    User user =
        UserLocalServiceUtil.addUser(
            ldapUser.getCreatorUserId(),
            companyId,
            autoPassword,
            password,
            password,
            ldapUser.isAutoScreenName(),
            ldapUser.getScreenName(),
            ldapUser.getEmailAddress(),
            0,
            StringPool.BLANK,
            ldapUser.getLocale(),
            ldapUser.getFirstName(),
            ldapUser.getMiddleName(),
            ldapUser.getLastName(),
            0,
            0,
            ldapUser.isMale(),
            birthdayMonth,
            birthdayDay,
            birthdayYear,
            StringPool.BLANK,
            ldapUser.getGroupIds(),
            ldapUser.getOrganizationIds(),
            ldapUser.getRoleIds(),
            ldapUser.getUserGroupIds(),
            ldapUser.isSendEmail(),
            ldapUser.getServiceContext());

    if (ldapUser.isUpdatePortrait()) {
      byte[] portraitBytes = ldapUser.getPortraitBytes();

      if ((portraitBytes != null) && (portraitBytes.length > 0)) {
        user = UserLocalServiceUtil.updatePortrait(user.getUserId(), portraitBytes);
      }
    }

    return user;
  }

  protected void addUserGroupsNotAddedByLDAPImport(long userId, List<Long> userGroupIds)
      throws Exception {

    List<UserGroup> userGroups = UserGroupLocalServiceUtil.getUserUserGroups(userId);

    for (UserGroup userGroup : userGroups) {
      if (!userGroupIds.contains(userGroup.getUserGroupId()) && !userGroup.isAddedByLDAPImport()) {

        userGroupIds.add(userGroup.getUserGroupId());
      }
    }
  }

  protected String escapeValue(String value) {
    return StringUtil.replace(value, "\\,", "\\\\,");
  }

  protected User getUser(long companyId, LDAPUser ldapUser) throws Exception {
    User user = null;

    try {
      String authType =
          PrefsPropsUtil.getString(
              companyId,
              PropsKeys.COMPANY_SECURITY_AUTH_TYPE,
              PropsValues.COMPANY_SECURITY_AUTH_TYPE);

      if (authType.equals(CompanyConstants.AUTH_TYPE_SN) && !ldapUser.isAutoScreenName()) {

        user = UserLocalServiceUtil.getUserByScreenName(companyId, ldapUser.getScreenName());
      } else {
        user = UserLocalServiceUtil.getUserByEmailAddress(companyId, ldapUser.getEmailAddress());
      }
    } catch (NoSuchUserException nsue) {
    }

    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);
  }

  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);
        }
      }
    }
  }

  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 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 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 User importUser(
      long companyId,
      Attributes attributes,
      Properties userMappings,
      Properties userExpandoMappings,
      Properties contactMappings,
      Properties contactExpandoMappings,
      String password)
      throws Exception {

    LDAPUserTransactionThreadLocal.setOriginatesFromLDAP(true);

    try {
      AttributesTransformer attributesTransformer = AttributesTransformerFactory.getInstance();

      attributes = attributesTransformer.transformUser(attributes);

      LDAPUser ldapUser =
          _ldapToPortalConverter.importLDAPUser(
              companyId,
              attributes,
              userMappings,
              userExpandoMappings,
              contactMappings,
              contactExpandoMappings,
              password);

      User user = getUser(companyId, ldapUser);

      if ((user != null) && user.isDefaultUser()) {
        return user;
      }

      if (user == null) {
        user = addUser(companyId, ldapUser, password);
      }

      String modifiedDate = LDAPUtil.getAttributeString(attributes, "modifyTimestamp");

      user = updateUser(companyId, ldapUser, user, password, modifiedDate);

      updateExpandoAttributes(user, ldapUser);

      return user;
    } finally {
      LDAPUserTransactionThreadLocal.setOriginatesFromLDAP(false);
    }
  }

  protected UserGroup importUserGroup(
      long companyId, Attributes attributes, Properties groupMappings) throws Exception {

    AttributesTransformer attributesTransformer = AttributesTransformerFactory.getInstance();

    attributes = attributesTransformer.transformGroup(attributes);

    LDAPGroup ldapGroup =
        _ldapToPortalConverter.importLDAPGroup(companyId, attributes, groupMappings);

    UserGroup userGroup = null;

    try {
      userGroup = UserGroupLocalServiceUtil.getUserGroup(companyId, ldapGroup.getGroupName());

      UserGroupLocalServiceUtil.updateUserGroup(
          companyId,
          userGroup.getUserGroupId(),
          ldapGroup.getGroupName(),
          ldapGroup.getDescription());
    } catch (NoSuchUserGroupException nsuge) {
      if (_log.isDebugEnabled()) {
        _log.debug("Adding user group to portal " + ldapGroup.getGroupName());
      }

      long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);

      LDAPUserGroupTransactionThreadLocal.setOriginatesFromLDAP(true);

      try {
        userGroup =
            UserGroupLocalServiceUtil.addUserGroup(
                defaultUserId, companyId, ldapGroup.getGroupName(), ldapGroup.getDescription());
      } catch (Exception e) {
        if (_log.isWarnEnabled()) {
          _log.warn("Unable to create user group " + ldapGroup.getGroupName());
        }

        if (_log.isDebugEnabled()) {
          _log.debug(e, e);
        }
      } finally {
        LDAPUserGroupTransactionThreadLocal.setOriginatesFromLDAP(false);
      }
    }

    addRole(companyId, ldapGroup, userGroup);

    return userGroup;
  }

  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());
      }
    }
  }

  protected void populateExpandoAttributes(
      ExpandoBridge expandoBridge, Map<String, String[]> expandoAttributes) {

    for (Map.Entry<String, String[]> expandoAttribute : expandoAttributes.entrySet()) {

      String name = expandoAttribute.getKey();

      if (!expandoBridge.hasAttribute(name)) {
        continue;
      }

      int type = expandoBridge.getAttributeType(name);

      Serializable value =
          ExpandoConverterUtil.getAttributeFromStringArray(type, expandoAttribute.getValue());

      try {
        ExpandoValueLocalServiceUtil.addValue(
            expandoBridge.getCompanyId(),
            expandoBridge.getClassName(),
            ExpandoTableConstants.DEFAULT_TABLE_NAME,
            name,
            expandoBridge.getClassPK(),
            value);
      } catch (Exception e) {
        _log.error(e, e);
      }
    }
  }

  protected void updateExpandoAttributes(User user, LDAPUser ldapUser) throws Exception {

    ExpandoBridge userExpandoBridge = user.getExpandoBridge();

    populateExpandoAttributes(userExpandoBridge, ldapUser.getUserExpandoAttributes());

    Contact contact = user.getContact();

    ExpandoBridge contactExpandoBridge = contact.getExpandoBridge();

    populateExpandoAttributes(contactExpandoBridge, ldapUser.getContactExpandoAttributes());
  }

  protected void updateLDAPUser(User ldapUser, Contact ldapContact, User user)
      throws PortalException, SystemException {

    Contact contact = user.getContact();

    ldapContact.setAimSn(GetterUtil.getString(contact.getAimSn()));
    ldapContact.setFacebookSn(GetterUtil.getString(contact.getFacebookSn()));
    ldapContact.setIcqSn(GetterUtil.getString(contact.getIcqSn()));
    ldapContact.setJabberSn(GetterUtil.getString(contact.getJabberSn()));
    ldapContact.setMale(GetterUtil.getBoolean(contact.getMale()));
    ldapContact.setMsnSn(GetterUtil.getString(contact.getMsnSn()));
    ldapContact.setMySpaceSn(GetterUtil.getString(contact.getMySpaceSn()));
    ldapContact.setPrefixId(GetterUtil.getInteger(contact.getPrefixId()));
    ldapContact.setSkypeSn(GetterUtil.getString(contact.getSkypeSn()));
    ldapContact.setSmsSn(GetterUtil.getString(contact.getSmsSn()));
    ldapContact.setSuffixId(GetterUtil.getInteger(contact.getSuffixId()));
    ldapContact.setTwitterSn(GetterUtil.getString(contact.getTwitterSn()));
    ldapContact.setYmSn(GetterUtil.getString(contact.getYmSn()));

    ldapUser.setComments(GetterUtil.getString(user.getComments()));
    ldapUser.setGreeting(GetterUtil.getString(user.getGreeting()));
    ldapUser.setJobTitle(GetterUtil.getString(user.getJobTitle()));
    ldapUser.setLanguageId(GetterUtil.getString(user.getLanguageId()));
    ldapUser.setMiddleName(GetterUtil.getString(user.getMiddleName()));
    ldapUser.setOpenId(GetterUtil.getString(user.getOpenId()));
    ldapUser.setTimeZoneId(GetterUtil.getString(user.getTimeZoneId()));
  }

  protected User updateUser(
      long companyId, LDAPUser ldapUser, User user, String password, String modifiedDate)
      throws Exception {

    Date ldapUserModifiedDate = null;

    try {
      if (Validator.isNull(modifiedDate)) {
        if (_log.isInfoEnabled()) {
          _log.info("LDAP entry never modified, skipping user " + user.getEmailAddress());
        }

        return user;
      } else {
        ldapUserModifiedDate = LDAPUtil.parseDate(modifiedDate);
      }

      if (ldapUserModifiedDate.equals(user.getModifiedDate()) && ldapUser.isAutoPassword()) {

        if (_log.isDebugEnabled()) {
          _log.debug("User is already synchronized, skipping user " + user.getEmailAddress());
        }

        return user;
      }
    } catch (ParseException pe) {
      if (_log.isDebugEnabled()) {
        _log.debug("Unable to parse LDAP modify timestamp " + modifiedDate, pe);
      }
    }

    boolean passwordReset = ldapUser.isPasswordReset();

    if (PrefsPropsUtil.getBoolean(
        companyId, PropsKeys.LDAP_EXPORT_ENABLED, PropsValues.LDAP_EXPORT_ENABLED)) {

      passwordReset = user.isPasswordReset();
    }

    if (!PropsValues.LDAP_IMPORT_USER_PASSWORD_ENABLED) {
      password = PropsValues.LDAP_IMPORT_USER_PASSWORD_DEFAULT;

      if (password.equalsIgnoreCase(_USER_PASSWORD_SCREEN_NAME)) {
        password = ldapUser.getScreenName();
      }
    }

    if (Validator.isNull(ldapUser.getScreenName())) {
      ldapUser.setAutoScreenName(true);
    }

    if (ldapUser.isAutoScreenName()) {
      ScreenNameGenerator screenNameGenerator = ScreenNameGeneratorFactory.getInstance();

      ldapUser.setScreenName(
          screenNameGenerator.generate(companyId, user.getUserId(), ldapUser.getEmailAddress()));
    }

    Calendar birthdayCal = CalendarFactoryUtil.getCalendar();

    birthdayCal.setTime(user.getContact().getBirthday());

    int birthdayMonth = birthdayCal.get(Calendar.MONTH);
    int birthdayDay = birthdayCal.get(Calendar.DAY_OF_MONTH);
    int birthdayYear = birthdayCal.get(Calendar.YEAR);

    if (ldapUser.isUpdatePassword()) {
      UserLocalServiceUtil.updatePassword(
          user.getUserId(), password, password, passwordReset, true);
    }

    Contact contact = user.getContact();

    Set<String> ldapIgnoreAttributes = SetUtil.fromArray(PropsValues.LDAP_USER_IGNORE_ATTRIBUTES);

    for (String attribute : ldapIgnoreAttributes) {
      Object value = BeanPropertiesUtil.getObjectSilent(user, attribute);

      if (value == null) {
        value = BeanPropertiesUtil.getObjectSilent(contact, attribute);
      }

      if (value != null) {
        BeanPropertiesUtil.setProperty(ldapUser, attribute, value);
      }
    }

    updateLDAPUser(ldapUser.getUser(), ldapUser.getContact(), user);

    user =
        UserLocalServiceUtil.updateUser(
            user.getUserId(),
            password,
            StringPool.BLANK,
            StringPool.BLANK,
            passwordReset,
            ldapUser.getReminderQueryQuestion(),
            ldapUser.getReminderQueryAnswer(),
            ldapUser.getScreenName(),
            ldapUser.getEmailAddress(),
            ldapUser.getFacebookId(),
            ldapUser.getOpenId(),
            ldapUser.getLanguageId(),
            ldapUser.getTimeZoneId(),
            ldapUser.getGreeting(),
            ldapUser.getComments(),
            ldapUser.getFirstName(),
            ldapUser.getMiddleName(),
            ldapUser.getLastName(),
            ldapUser.getPrefixId(),
            ldapUser.getSuffixId(),
            ldapUser.isMale(),
            birthdayMonth,
            birthdayDay,
            birthdayYear,
            ldapUser.getSmsSn(),
            ldapUser.getAimSn(),
            ldapUser.getFacebookSn(),
            ldapUser.getIcqSn(),
            ldapUser.getJabberSn(),
            ldapUser.getMsnSn(),
            ldapUser.getMySpaceSn(),
            ldapUser.getSkypeSn(),
            ldapUser.getTwitterSn(),
            ldapUser.getYmSn(),
            ldapUser.getJobTitle(),
            ldapUser.getGroupIds(),
            ldapUser.getOrganizationIds(),
            ldapUser.getRoleIds(),
            ldapUser.getUserGroupRoles(),
            ldapUser.getUserGroupIds(),
            ldapUser.getServiceContext());

    if (ldapUserModifiedDate != null) {
      user = UserLocalServiceUtil.updateModifiedDate(user.getUserId(), ldapUserModifiedDate);
    }

    if (ldapUser.isUpdatePortrait()) {
      byte[] portraitBytes = ldapUser.getPortraitBytes();

      if ((portraitBytes != null) && (portraitBytes.length > 0)) {
        UserLocalServiceUtil.updatePortrait(user.getUserId(), portraitBytes);
      } else {
        UserLocalServiceUtil.deletePortrait(user.getUserId());
      }
    }

    return user;
  }

  private static final String _IMPORT_BY_GROUP = "group";

  private static final String _IMPORT_BY_USER = "******";

  private static final String _USER_PASSWORD_SCREEN_NAME = "screenName";

  private static Log _log = LogFactoryUtil.getLog(PortalLDAPImporterImpl.class);

  private LDAPToPortalConverter _ldapToPortalConverter;
  private PortalCache _portalCache =
      SingleVMPoolUtil.getCache(PortalLDAPImporter.class.getName(), false);
}
/**
 * @author Bruno Farache
 * @author Marcus Schmidke
 * @author Brian Wing Shun Chan
 * @author Wesley Gong
 * @author Marcellus Tavares
 * @author Michael C. Han
 */
public class NtlmFilter extends BasePortalFilter {

  @Override
  public void init(FilterConfig filterConfig) {
    super.init(filterConfig);

    try {
      Properties properties = PropsUtil.getProperties("jcifs.", false);

      for (Map.Entry<Object, Object> entry : properties.entrySet()) {
        String key = (String) entry.getKey();
        String value = (String) entry.getValue();

        Config.setProperty(key, value);
      }
    } catch (Exception e) {
      _log.error(e, e);
    }
  }

  @Override
  public boolean isFilterEnabled(HttpServletRequest request, HttpServletResponse response) {

    try {
      long companyId = PortalInstances.getCompanyId(request);

      if (BrowserSnifferUtil.isIe(request) && AuthSettingsUtil.isNtlmEnabled(companyId)) {

        return true;
      }
    } catch (Exception e) {
      _log.error(e, e);
    }

    return false;
  }

  @Override
  protected Log getLog() {
    return _log;
  }

  protected NtlmManager getNtlmManager(long companyId) throws SystemException {

    String domain =
        PrefsPropsUtil.getString(companyId, PropsKeys.NTLM_DOMAIN, PropsValues.NTLM_DOMAIN);
    String domainController =
        PrefsPropsUtil.getString(
            companyId, PropsKeys.NTLM_DOMAIN_CONTROLLER, PropsValues.NTLM_DOMAIN_CONTROLLER);
    String domainControllerName =
        PrefsPropsUtil.getString(
            companyId,
            PropsKeys.NTLM_DOMAIN_CONTROLLER_NAME,
            PropsValues.NTLM_DOMAIN_CONTROLLER_NAME);
    String serviceAccount =
        PrefsPropsUtil.getString(
            companyId, PropsKeys.NTLM_SERVICE_ACCOUNT, PropsValues.NTLM_SERVICE_ACCOUNT);
    String servicePassword =
        PrefsPropsUtil.getString(
            companyId, PropsKeys.NTLM_SERVICE_PASSWORD, PropsValues.NTLM_SERVICE_PASSWORD);

    NtlmManager ntlmManager = _ntlmManagers.get(companyId);

    if (ntlmManager == null) {
      ntlmManager =
          new NtlmManager(
              domain, domainController, domainControllerName, serviceAccount, servicePassword);

      _ntlmManagers.put(companyId, ntlmManager);
    } else {
      if (!Validator.equals(ntlmManager.getDomain(), domain)
          || !Validator.equals(ntlmManager.getDomainController(), domainController)
          || !Validator.equals(ntlmManager.getDomainControllerName(), domainControllerName)
          || !Validator.equals(ntlmManager.getServiceAccount(), serviceAccount)
          || !Validator.equals(ntlmManager.getServicePassword(), servicePassword)) {

        ntlmManager.setConfiguration(
            domain, domainController, domainControllerName, serviceAccount, servicePassword);
      }
    }

    return ntlmManager;
  }

  protected String getPortalCacheKey(HttpServletRequest request) {
    HttpSession session = request.getSession(false);

    if (session == null) {
      return request.getRemoteAddr();
    }

    return session.getId();
  }

  @Override
  protected void processFilter(
      HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
      throws Exception {

    // Type 1 NTLM requests from browser can (and should) always immediately
    // be replied to with an Type 2 NTLM response, no matter whether we're
    // yet logging in or whether it is much later in the session.

    HttpSession session = request.getSession(false);

    long companyId = PortalInstances.getCompanyId(request);

    String authorization = GetterUtil.getString(request.getHeader(HttpHeaders.AUTHORIZATION));

    if (authorization.startsWith("NTLM")) {
      NtlmManager ntlmManager = getNtlmManager(companyId);

      String portalCacheKey = getPortalCacheKey(request);

      byte[] src = Base64.decode(authorization.substring(5));

      if (src[8] == 1) {
        byte[] serverChallenge = new byte[8];

        _secureRandom.nextBytes(serverChallenge);

        byte[] challengeMessage = ntlmManager.negotiate(src, serverChallenge);

        authorization = Base64.encode(challengeMessage);

        response.setContentLength(0);
        response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "NTLM " + authorization);
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

        response.flushBuffer();

        _portalCache.put(portalCacheKey, serverChallenge);

        // Interrupt filter chain, send response. Browser will
        // immediately post a new request.

        return;
      }

      byte[] serverChallenge = _portalCache.get(portalCacheKey);

      if (serverChallenge == null) {
        response.setContentLength(0);
        response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "NTLM");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

        response.flushBuffer();

        return;
      }

      NtlmUserAccount ntlmUserAccount = null;

      try {
        ntlmUserAccount = ntlmManager.authenticate(src, serverChallenge);
      } catch (Exception e) {
        if (_log.isErrorEnabled()) {
          _log.error("Unable to perform NTLM authentication", e);
        }
      } finally {
        _portalCache.remove(portalCacheKey);
      }

      if (ntlmUserAccount == null) {
        response.setContentLength(0);
        response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "NTLM");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

        response.flushBuffer();

        return;
      }

      if (_log.isDebugEnabled()) {
        _log.debug("NTLM remote user " + ntlmUserAccount.getUserName());
      }

      request.setAttribute(WebKeys.NTLM_REMOTE_USER, ntlmUserAccount.getUserName());

      if (session != null) {
        session.setAttribute(WebKeys.NTLM_USER_ACCOUNT, ntlmUserAccount);
      }
    }

    String path = request.getPathInfo();

    if ((path != null) && path.endsWith("/login")) {
      NtlmUserAccount ntlmUserAccount = null;

      if (session != null) {
        ntlmUserAccount = (NtlmUserAccount) session.getAttribute(WebKeys.NTLM_USER_ACCOUNT);
      }

      if (ntlmUserAccount == null) {
        response.setContentLength(0);
        response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "NTLM");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

        response.flushBuffer();

        return;
      } else {
        request.setAttribute(WebKeys.NTLM_REMOTE_USER, ntlmUserAccount.getUserName());
      }
    }

    processFilter(NtlmPostFilter.class, request, response, filterChain);
  }

  private static Log _log = LogFactoryUtil.getLog(NtlmFilter.class);

  private Map<Long, NtlmManager> _ntlmManagers = new ConcurrentHashMap<Long, NtlmManager>();
  private PortalCache<String, byte[]> _portalCache =
      SingleVMPoolUtil.getCache(NtlmFilter.class.getName());
  private SecureRandom _secureRandom = new SecureRandom();
}
/**
 * @author Brian Wing Shun Chan
 * @author Alexander Chow
 * @author Minhchau Dang
 * @author Raymond Augé
 */
@DoPrivileged
public class PortletPreferencesFactoryImpl implements PortletPreferencesFactory {

  @Override
  public void checkControlPanelPortletPreferences(ThemeDisplay themeDisplay, Portlet portlet)
      throws PortalException {

    Layout layout = themeDisplay.getLayout();

    Group group = layout.getGroup();

    if (!group.isControlPanel()) {
      return;
    }

    String portletId = portlet.getPortletId();

    boolean hasControlPanelAccessPermission =
        PortletPermissionUtil.hasControlPanelAccessPermission(
            themeDisplay.getPermissionChecker(), themeDisplay.getScopeGroupId(), portletId);

    if (!hasControlPanelAccessPermission) {
      return;
    }

    PortletPreferences portletSetup = getStrictLayoutPortletSetup(layout, portletId);

    if (portletSetup instanceof StrictPortletPreferencesImpl) {
      getLayoutPortletSetup(layout, portletId);
    }

    if (portlet.isInstanceable()) {
      return;
    }

    PortletPreferencesIds portletPreferencesIds =
        getPortletPreferencesIds(
            themeDisplay.getScopeGroupId(), themeDisplay.getUserId(), layout, portletId, false);

    PortletPreferences portletPreferences =
        PortletPreferencesLocalServiceUtil.fetchPreferences(portletPreferencesIds);

    if (portletPreferences != null) {
      return;
    }

    PortletPreferencesLocalServiceUtil.getPreferences(portletPreferencesIds);
  }

  @Override
  public PortletPreferences fromDefaultXML(String xml) {
    Map<String, Preference> preferencesMap = toPreferencesMap(xml);

    return new PortletPreferencesImpl(xml, preferencesMap);
  }

  @Override
  public PortalPreferencesImpl fromXML(long ownerId, int ownerType, String xml) {

    try {
      Map<String, Preference> preferencesMap = toPreferencesMap(xml);

      return new PortalPreferencesImpl(ownerId, ownerType, xml, preferencesMap, false);
    } catch (SystemException se) {
      throw se;
    }
  }

  @Override
  public PortletPreferencesImpl fromXML(
      long companyId, long ownerId, int ownerType, long plid, String portletId, String xml) {

    try {
      Map<String, Preference> preferencesMap = toPreferencesMap(xml);

      return new PortletPreferencesImpl(
          companyId, ownerId, ownerType, plid, portletId, xml, preferencesMap);
    } catch (SystemException se) {
      throw se;
    }
  }

  /** @deprecated As of 6.2.0, replaced by {@link #fromXML(long, int, String)} */
  @Deprecated
  @Override
  public PortalPreferences fromXML(long companyId, long ownerId, int ownerType, String xml) {

    return fromXML(ownerId, ownerType, xml);
  }

  @Override
  public PortletPreferences getLayoutPortletSetup(Layout layout, String portletId) {

    long ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
    int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;

    if (PortletConstants.hasUserId(portletId)) {
      ownerId = PortletConstants.getUserId(portletId);
      ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
    }

    return PortletPreferencesLocalServiceUtil.getPreferences(
        layout.getCompanyId(), ownerId, ownerType, layout.getPlid(), portletId);
  }

  @Override
  public PortalPreferences getPortalPreferences(HttpServletRequest request) {
    ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);

    return getPortalPreferences(
        request.getSession(), themeDisplay.getUserId(), themeDisplay.isSignedIn());
  }

  @Override
  public PortalPreferences getPortalPreferences(
      HttpSession session, long userId, boolean signedIn) {

    long ownerId = userId;
    int ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;

    PortalPreferences portalPreferences = null;

    if (signedIn) {
      PortalPreferencesWrapper portalPreferencesWrapper =
          PortalPreferencesWrapperCacheUtil.get(ownerId, ownerType);

      if (portalPreferencesWrapper == null) {
        portalPreferencesWrapper =
            (PortalPreferencesWrapper)
                PortalPreferencesLocalServiceUtil.getPreferences(ownerId, ownerType);

        portalPreferences = portalPreferencesWrapper.getPortalPreferencesImpl();
      } else {
        PortalPreferencesImpl portalPreferencesImpl =
            portalPreferencesWrapper.getPortalPreferencesImpl();

        portalPreferences = portalPreferencesImpl.clone();
      }
    } else {
      if (session != null) {
        portalPreferences = (PortalPreferences) session.getAttribute(WebKeys.PORTAL_PREFERENCES);
      }

      if (portalPreferences == null) {
        PortalPreferencesWrapper portalPreferencesWrapper =
            PortalPreferencesWrapperCacheUtil.get(ownerId, ownerType);

        if (portalPreferencesWrapper == null) {
          portalPreferencesWrapper =
              (PortalPreferencesWrapper)
                  PortalPreferencesLocalServiceUtil.getPreferences(ownerId, ownerType);

          portalPreferences = portalPreferencesWrapper.getPortalPreferencesImpl();
        } else {
          PortalPreferencesImpl portalPreferencesImpl =
              portalPreferencesWrapper.getPortalPreferencesImpl();

          portalPreferences = portalPreferencesImpl.clone();
        }

        if (session != null) {
          session.setAttribute(WebKeys.PORTAL_PREFERENCES, portalPreferences);
        }
      }
    }

    portalPreferences.setSignedIn(signedIn);
    portalPreferences.setUserId(userId);

    return portalPreferences;
  }

  /**
   * @deprecated As of 6.2.0, replaced by {@link #getPortalPreferences(HttpSession, long, boolean)}
   */
  @Deprecated
  @Override
  public PortalPreferences getPortalPreferences(
      HttpSession session, long companyId, long userId, boolean signedIn) {

    return getPortalPreferences(session, userId, signedIn);
  }

  @Override
  public PortalPreferences getPortalPreferences(long userId, boolean signedIn) {

    return getPortalPreferences(null, userId, signedIn);
  }

  /** @deprecated As of 6.2.0, replaced by {@link #getPortalPreferences(long, boolean)} */
  @Deprecated
  @Override
  public PortalPreferences getPortalPreferences(long companyId, long userId, boolean signedIn) {

    return getPortalPreferences(userId, signedIn);
  }

  @Override
  public PortalPreferences getPortalPreferences(PortletRequest portletRequest) {

    HttpServletRequest request = PortalUtil.getHttpServletRequest(portletRequest);

    return getPortalPreferences(request);
  }

  @Override
  public PortletPreferences getPortletPreferences(HttpServletRequest request, String portletId)
      throws PortalException {

    PortletPreferencesIds portletPreferencesIds = getPortletPreferencesIds(request, portletId);

    return PortletPreferencesLocalServiceUtil.getPreferences(portletPreferencesIds);
  }

  @Override
  public PortletPreferencesIds getPortletPreferencesIds(
      HttpServletRequest request, Layout layout, String portletId) throws PortalException {

    ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);

    long siteGroupId = themeDisplay.getSiteGroupId();
    long userId = PortalUtil.getUserId(request);
    LayoutTypePortlet layoutTypePortlet = themeDisplay.getLayoutTypePortlet();

    boolean modeEditGuest = false;

    String portletMode = ParamUtil.getString(request, "p_p_mode");

    if (portletMode.equals(LiferayPortletMode.EDIT_GUEST.toString())
        || ((layoutTypePortlet != null)
            && layoutTypePortlet.hasModeEditGuestPortletId(portletId))) {

      modeEditGuest = true;
    }

    return getPortletPreferencesIds(siteGroupId, userId, layout, portletId, modeEditGuest);
  }

  @Override
  public PortletPreferencesIds getPortletPreferencesIds(
      HttpServletRequest request, String portletId) throws PortalException {

    Layout layout = (Layout) request.getAttribute(WebKeys.LAYOUT);

    return getPortletPreferencesIds(request, layout, portletId);
  }

  @Override
  public PortletPreferencesIds getPortletPreferencesIds(
      long siteGroupId, long userId, Layout layout, String portletId, boolean modeEditGuest)
      throws PortalException {

    PermissionChecker permissionChecker = PermissionThreadLocal.getPermissionChecker();

    String originalPortletId = portletId;

    Portlet portlet = PortletLocalServiceUtil.getPortletById(layout.getCompanyId(), portletId);

    long ownerId = 0;
    int ownerType = 0;
    long plid = 0;

    if (modeEditGuest) {
      boolean hasUpdateLayoutPermission =
          LayoutPermissionUtil.contains(permissionChecker, layout, ActionKeys.UPDATE);

      if (!layout.isPrivateLayout() && hasUpdateLayoutPermission) {
      } else {

        // Only users with the correct permissions can update guest
        // preferences

        throw new PrincipalException();
      }
    }

    if (PortletConstants.hasUserId(originalPortletId)
        && (PortletConstants.getUserId(originalPortletId) == userId)) {

      ownerId = userId;
      ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
      plid = layout.getPlid();
    } else if (portlet.isPreferencesCompanyWide()) {
      ownerId = layout.getCompanyId();
      ownerType = PortletKeys.PREFS_OWNER_TYPE_COMPANY;
      plid = PortletKeys.PREFS_PLID_SHARED;
      portletId = PortletConstants.getRootPortletId(portletId);
    } else {
      if (portlet.isPreferencesUniquePerLayout()) {
        ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
        ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
        plid = layout.getPlid();

        if (portlet.isPreferencesOwnedByGroup()) {
        } else {
          if ((userId <= 0) || modeEditGuest) {
            userId = UserLocalServiceUtil.getDefaultUserId(layout.getCompanyId());
          }

          ownerId = userId;
          ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
        }
      } else {
        plid = PortletKeys.PREFS_PLID_SHARED;

        if (portlet.isPreferencesOwnedByGroup()) {
          ownerId = siteGroupId;
          ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
          portletId = PortletConstants.getRootPortletId(portletId);
        } else {
          if ((userId <= 0) || modeEditGuest) {
            userId = UserLocalServiceUtil.getDefaultUserId(layout.getCompanyId());
          }

          ownerId = userId;
          ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
        }
      }
    }

    return new PortletPreferencesIds(layout.getCompanyId(), ownerId, ownerType, plid, portletId);
  }

  @Override
  public PortletPreferences getPortletSetup(HttpServletRequest request, String portletId) {

    return getPortletSetup(request, portletId, null);
  }

  @Override
  public PortletPreferences getPortletSetup(
      HttpServletRequest request, String portletId, String defaultPreferences) {

    PortletRequest portletRequest =
        (PortletRequest) request.getAttribute(JavaConstants.JAVAX_PORTLET_REQUEST);

    if (portletRequest instanceof ConfigurationPortletRequest) {
      PortletRequestWrapper portletRequestWrapper = (PortletRequestWrapper) portletRequest;

      return portletRequestWrapper.getPreferences();
    }

    ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);

    return getPortletSetup(
        themeDisplay.getSiteGroupId(), themeDisplay.getLayout(), portletId, defaultPreferences);
  }

  @Override
  public PortletPreferences getPortletSetup(
      Layout layout, String portletId, String defaultPreferences) {

    return getPortletSetup(LayoutConstants.DEFAULT_PLID, layout, portletId, defaultPreferences);
  }

  @Override
  public PortletPreferences getPortletSetup(
      long siteGroupId, Layout layout, String portletId, String defaultPreferences) {

    return getPortletSetup(siteGroupId, layout, portletId, defaultPreferences, false);
  }

  @Override
  public PortletPreferences getPortletSetup(PortletRequest portletRequest) {
    String portletId = PortalUtil.getPortletId(portletRequest);

    return getPortletSetup(portletRequest, portletId);
  }

  @Override
  public PortletPreferences getPortletSetup(PortletRequest portletRequest, String portletId) {

    if (portletRequest instanceof ConfigurationPortletRequest) {
      PortletRequestWrapper portletRequestWrapper = (PortletRequestWrapper) portletRequest;

      return portletRequestWrapper.getPreferences();
    }

    HttpServletRequest request = PortalUtil.getHttpServletRequest(portletRequest);

    return getPortletSetup(request, portletId);
  }

  @Override
  public Map<Long, PortletPreferences> getPortletSetupMap(
      long companyId,
      long groupId,
      long ownerId,
      int ownerType,
      String portletId,
      boolean privateLayout) {

    Map<Long, PortletPreferences> portletSetupMap = new HashMap<Long, PortletPreferences>();

    List<com.liferay.portal.model.PortletPreferences> portletPreferencesList =
        PortletPreferencesLocalServiceUtil.getPortletPreferences(
            companyId, groupId, ownerId, ownerType, portletId, privateLayout);

    for (com.liferay.portal.model.PortletPreferences portletPreferences : portletPreferencesList) {

      PortletPreferences portletSetup =
          PortletPreferencesLocalServiceUtil.getPreferences(
              companyId, ownerId, ownerType, portletPreferences.getPlid(), portletId);

      portletSetupMap.put(portletPreferences.getPlid(), portletSetup);
    }

    return portletSetupMap;
  }

  @Override
  public PortletPreferences getPreferences(HttpServletRequest request) {
    PortletRequest portletRequest =
        (PortletRequest) request.getAttribute(JavaConstants.JAVAX_PORTLET_REQUEST);

    PortletPreferences portletPreferences = null;

    if (portletRequest != null) {
      PortletPreferencesWrapper portletPreferencesWrapper =
          (PortletPreferencesWrapper) portletRequest.getPreferences();

      portletPreferences = portletPreferencesWrapper.getPortletPreferencesImpl();
    }

    return portletPreferences;
  }

  @Override
  public PreferencesValidator getPreferencesValidator(Portlet portlet) {
    return PortalUtil.getPreferencesValidator(portlet);
  }

  @Override
  public PortletPreferences getStrictLayoutPortletSetup(Layout layout, String portletId) {

    long ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
    int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;

    if (PortletConstants.hasUserId(portletId)) {
      ownerId = PortletConstants.getUserId(portletId);
      ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
    }

    return PortletPreferencesLocalServiceUtil.getStrictPreferences(
        layout.getCompanyId(), ownerId, ownerType, layout.getPlid(), portletId);
  }

  @Override
  public PortletPreferences getStrictPortletSetup(Layout layout, String portletId) {

    return getPortletSetup(LayoutConstants.DEFAULT_PLID, layout, portletId, StringPool.BLANK, true);
  }

  @Override
  public String toXML(PortalPreferences portalPreferences) {
    PortalPreferencesImpl portalPreferencesImpl = null;

    if (portalPreferences instanceof PortalPreferencesWrapper) {
      PortalPreferencesWrapper portalPreferencesWrapper =
          (PortalPreferencesWrapper) portalPreferences;

      portalPreferencesImpl = portalPreferencesWrapper.getPortalPreferencesImpl();
    } else {
      portalPreferencesImpl = (PortalPreferencesImpl) portalPreferences;
    }

    return portalPreferencesImpl.toXML();
  }

  @Override
  public String toXML(PortletPreferences portletPreferences) {
    PortletPreferencesImpl portletPreferencesImpl = null;

    if (portletPreferences instanceof PortletPreferencesWrapper) {
      PortletPreferencesWrapper portletPreferencesWrapper =
          (PortletPreferencesWrapper) portletPreferences;

      portletPreferencesImpl = portletPreferencesWrapper.getPortletPreferencesImpl();
    } else {
      portletPreferencesImpl = (PortletPreferencesImpl) portletPreferences;
    }

    return portletPreferencesImpl.toXML();
  }

  protected PortletPreferences getPortletSetup(
      long siteGroupId,
      Layout layout,
      String portletId,
      String defaultPreferences,
      boolean strictMode) {

    String originalPortletId = portletId;

    Portlet portlet = PortletLocalServiceUtil.getPortletById(layout.getCompanyId(), portletId);

    boolean uniquePerLayout = false;
    boolean uniquePerGroup = false;

    if (portlet.isPreferencesCompanyWide()) {
      portletId = PortletConstants.getRootPortletId(portletId);
    } else {
      if (portlet.isPreferencesUniquePerLayout()) {
        uniquePerLayout = true;

        if (portlet.isPreferencesOwnedByGroup()) {
          uniquePerGroup = true;
        }
      } else {
        if (portlet.isPreferencesOwnedByGroup()) {
          uniquePerGroup = true;
          portletId = PortletConstants.getRootPortletId(portletId);
        }
      }
    }

    long ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
    int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
    long plid = layout.getPlid();

    Group group = GroupLocalServiceUtil.fetchGroup(siteGroupId);

    if ((group != null) && group.isLayout()) {
      plid = group.getClassPK();
    }

    if (PortletConstants.hasUserId(originalPortletId)) {
      ownerId = PortletConstants.getUserId(originalPortletId);
      ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
    } else if (!uniquePerLayout) {
      plid = PortletKeys.PREFS_PLID_SHARED;

      if (uniquePerGroup) {
        if (siteGroupId > LayoutConstants.DEFAULT_PLID) {
          ownerId = siteGroupId;
        } else {
          ownerId = layout.getGroupId();
        }

        ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
      } else {
        ownerId = layout.getCompanyId();
        ownerType = PortletKeys.PREFS_OWNER_TYPE_COMPANY;
      }
    }

    if (strictMode) {
      return PortletPreferencesLocalServiceUtil.getStrictPreferences(
          layout.getCompanyId(), ownerId, ownerType, plid, portletId);
    }

    return PortletPreferencesLocalServiceUtil.getPreferences(
        layout.getCompanyId(), ownerId, ownerType, plid, portletId, defaultPreferences);
  }

  protected Preference readPreference(XMLEventReader xmlEventReader) throws XMLStreamException {

    String name = null;
    List<String> values = new ArrayList<String>();
    boolean readOnly = false;

    while (xmlEventReader.hasNext()) {
      XMLEvent xmlEvent = xmlEventReader.nextEvent();

      if (xmlEvent.isStartElement()) {
        StartElement startElement = xmlEvent.asStartElement();

        String elementName = startElement.getName().getLocalPart();

        if (elementName.equals("name")) {
          name = StAXReaderUtil.read(xmlEventReader);
        } else if (elementName.equals("value")) {
          String value = StAXReaderUtil.read(xmlEventReader);

          values.add(value);
        } else if (elementName.equals("read-only")) {
          String value = StAXReaderUtil.read(xmlEventReader);

          readOnly = GetterUtil.getBoolean(value);
        }
      } else if (xmlEvent.isEndElement()) {
        EndElement endElement = xmlEvent.asEndElement();

        String elementName = endElement.getName().getLocalPart();

        if (elementName.equals("preference")) {
          break;
        }
      }
    }

    return new Preference(name, values.toArray(new String[values.size()]), readOnly);
  }

  protected Map<String, Preference> toPreferencesMap(String xml) {
    if (Validator.isNull(xml)) {
      return Collections.emptyMap();
    }

    Map<String, Preference> preferencesMap = _preferencesMapPortalCache.get(xml);

    if (preferencesMap != null) {
      return preferencesMap;
    }

    XMLEventReader xmlEventReader = null;

    try {
      XMLInputFactory xmlInputFactory = StAXReaderUtil.getXMLInputFactory();

      xmlEventReader = xmlInputFactory.createXMLEventReader(new UnsyncStringReader(xml));

      while (xmlEventReader.hasNext()) {
        XMLEvent xmlEvent = xmlEventReader.nextEvent();

        if (xmlEvent.isStartElement()) {
          StartElement startElement = xmlEvent.asStartElement();

          String elementName = startElement.getName().getLocalPart();

          if (elementName.equals("preference")) {
            Preference preference = readPreference(xmlEventReader);

            if (preferencesMap == null) {
              preferencesMap = new HashMap<String, Preference>();
            }

            preferencesMap.put(preference.getName(), preference);
          }
        }
      }
    } catch (XMLStreamException xse) {
      throw new SystemException(xse);
    } finally {
      if (xmlEventReader != null) {
        try {
          xmlEventReader.close();
        } catch (XMLStreamException xse) {
        }
      }
    }

    if (preferencesMap == null) {
      preferencesMap = Collections.emptyMap();
    }

    _preferencesMapPortalCache.put(xml, preferencesMap);

    return preferencesMap;
  }

  private PortalCache<String, Map<String, Preference>> _preferencesMapPortalCache =
      SingleVMPoolUtil.getCache(PortletPreferencesFactoryImpl.class.getName());
}