public static List<User> getThreadUsers(long userId, long mbThreadId)
      throws PortalException, SystemException {

    List<User> users = new ArrayList<User>();

    // Users who have contributed to the thread

    List<MBMessage> mbMessages =
        UserThreadServiceUtil.getThreadMessages(
            mbThreadId, QueryUtil.ALL_POS, QueryUtil.ALL_POS, false);

    for (MBMessage mbMessage : mbMessages) {
      if (userId == mbMessage.getUserId()) {
        continue;
      }

      User user = UserLocalServiceUtil.fetchUser(mbMessage.getUserId());

      if (user == null) {
        user = UserLocalServiceUtil.createUser(mbMessage.getUserId());

        user.setFirstName(mbMessage.getUserName());
        user.setStatus(WorkflowConstants.STATUS_INACTIVE);
      }

      if (!users.contains(user)) {
        users.add(user);
      }
    }

    // Users who can view the thread

    List<UserThread> userThreads = UserThreadLocalServiceUtil.getMBThreadUserThreads(mbThreadId);

    for (UserThread userThread : userThreads) {
      if (userId == userThread.getUserId()) {
        continue;
      }

      User user = UserLocalServiceUtil.fetchUser(userThread.getUserId());

      if (user == null) {
        user = UserLocalServiceUtil.createUser(userThread.getUserId());

        user.setFirstName(userThread.getUserName());
        user.setStatus(WorkflowConstants.STATUS_INACTIVE);
      }

      if (!users.contains(user)) {
        users.add(user);
      }
    }

    return users;
  }
  private static void _populateThreadLocalsFromContext(Map<String, Serializable> context) {

    long companyId = GetterUtil.getLong(context.get("companyId"));

    if (companyId > 0) {
      CompanyThreadLocal.setCompanyId(companyId);
    }

    Locale defaultLocale = (Locale) context.get("defaultLocale");

    if (defaultLocale != null) {
      LocaleThreadLocal.setDefaultLocale(defaultLocale);
    }

    long groupId = GetterUtil.getLong(context.get("groupId"));

    if (groupId > 0) {
      GroupThreadLocal.setGroupId(groupId);
    }

    String principalName = GetterUtil.getString(context.get("principalName"));

    if (Validator.isNotNull(principalName)) {
      PrincipalThreadLocal.setName(principalName);
    }

    PermissionChecker permissionChecker = null;

    if (Validator.isNotNull(principalName)) {
      try {
        User user = UserLocalServiceUtil.fetchUser(PrincipalThreadLocal.getUserId());

        permissionChecker = PermissionCheckerFactoryUtil.create(user);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }

    if (permissionChecker != null) {
      PermissionThreadLocal.setPermissionChecker(permissionChecker);
    }

    String principalPassword = GetterUtil.getString(context.get("principalPassword"));

    if (Validator.isNotNull(principalPassword)) {
      PrincipalThreadLocal.setPassword(principalPassword);
    }

    Locale siteDefaultLocale = (Locale) context.get("siteDefaultLocale");

    if (siteDefaultLocale != null) {
      LocaleThreadLocal.setSiteDefaultLocale(siteDefaultLocale);
    }

    Locale themeDisplayLocale = (Locale) context.get("themeDisplayLocale");

    if (themeDisplayLocale != null) {
      LocaleThreadLocal.setThemeDisplayLocale(themeDisplayLocale);
    }
  }
  @Override
  public AnonymousUser addAnonymousUser(
      long userId, String lastIp, String typeSettings, ServiceContext serviceContext)
      throws PortalException, SystemException {

    User user = UserLocalServiceUtil.fetchUser(userId);

    Date now = new Date();

    long anonymousUserId = CounterLocalServiceUtil.increment();

    AnonymousUser anonymousUser = anonymousUserPersistence.create(anonymousUserId);

    anonymousUser.setCompanyId(serviceContext.getCompanyId());

    if (user != null) {
      anonymousUser.setUserId(user.getUserId());
      anonymousUser.setUserName(user.getFullName());
    }

    anonymousUser.setCreateDate(serviceContext.getCreateDate(now));
    anonymousUser.setModifiedDate(serviceContext.getModifiedDate(now));
    anonymousUser.setLastIp(lastIp);
    anonymousUser.setTypeSettings(typeSettings);

    anonymousUserPersistence.update(anonymousUser);

    return anonymousUser;
  }
  @Override
  public AnonymousUser updateAnonymousUser(
      long anonymousUserId,
      long userId,
      String lastIp,
      String typeSettings,
      ServiceContext serviceContext)
      throws PortalException, SystemException {

    Date now = new Date();

    AnonymousUser anonymousUser = anonymousUserPersistence.findByPrimaryKey(anonymousUserId);

    User user = UserLocalServiceUtil.fetchUser(userId);

    if (user != null) {
      anonymousUser.setUserId(user.getUserId());
      anonymousUser.setUserName(user.getFullName());
    }

    anonymousUser.setModifiedDate(serviceContext.getModifiedDate(now));
    anonymousUser.setLastIp(lastIp);
    anonymousUser.setTypeSettings(typeSettings);

    anonymousUserPersistence.update(anonymousUser);

    return anonymousUser;
  }
  @Override
  public long[] getPooledActorsIds(long companyId, long workflowTaskInstanceId)
      throws WorkflowException {

    try {
      KaleoTaskInstanceToken kaleoTaskInstanceToken =
          KaleoTaskInstanceTokenLocalServiceUtil.getKaleoTaskInstanceToken(workflowTaskInstanceId);

      List<KaleoTaskAssignment> calculatedKaleoTaskAssignments =
          getCalculatedKaleoTaskAssignments(kaleoTaskInstanceToken);

      Map<String, Long> pooledActors = new TreeMap<>(new NaturalOrderStringComparator());

      for (KaleoTaskAssignment calculatedKaleoTaskAssignment : calculatedKaleoTaskAssignments) {

        String assigneeClassName = calculatedKaleoTaskAssignment.getAssigneeClassName();
        long assigneeClassPK = calculatedKaleoTaskAssignment.getAssigneeClassPK();

        if (assigneeClassName.equals(User.class.getName())) {
          User user = UserLocalServiceUtil.fetchUser(assigneeClassPK);

          if (user != null) {
            pooledActors.put(user.getFullName(), user.getUserId());
          }

          continue;
        }

        Role role =
            RoleLocalServiceUtil.getRole(calculatedKaleoTaskAssignment.getAssigneeClassPK());

        if ((role.getType() == RoleConstants.TYPE_SITE)
            || (role.getType() == RoleConstants.TYPE_ORGANIZATION)) {

          List<UserGroupRole> userGroupRoles =
              UserGroupRoleLocalServiceUtil.getUserGroupRolesByGroupAndRole(
                  kaleoTaskInstanceToken.getGroupId(), assigneeClassPK);

          for (UserGroupRole userGroupRole : userGroupRoles) {
            User user = userGroupRole.getUser();

            pooledActors.put(user.getFullName(), user.getUserId());
          }

          List<UserGroupGroupRole> userGroupGroupRoles =
              UserGroupGroupRoleLocalServiceUtil.getUserGroupGroupRolesByGroupAndRole(
                  kaleoTaskInstanceToken.getGroupId(), assigneeClassPK);

          for (UserGroupGroupRole userGroupGroupRole : userGroupGroupRoles) {

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

            for (User user : userGroupUsers) {
              pooledActors.put(user.getFullName(), user.getUserId());
            }
          }
        } else {
          List<User> inheritedRoleUsers =
              UserLocalServiceUtil.getInheritedRoleUsers(
                  assigneeClassPK, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null);

          for (User user : inheritedRoleUsers) {
            pooledActors.put(user.getFullName(), user.getUserId());
          }
        }
      }

      return ArrayUtil.toLongArray(pooledActors.values());
    } catch (Exception e) {
      throw new WorkflowException(e);
    }
  }
  protected void doImportPortletInfo(PortletDataContext portletDataContext, long userId)
      throws Exception {

    Map<String, String[]> parameterMap = portletDataContext.getParameterMap();

    boolean importPermissions =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PERMISSIONS);

    StopWatch stopWatch = new StopWatch();

    stopWatch.start();

    ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext();

    if (serviceContext == null) {
      serviceContext = new ServiceContext();

      serviceContext.setCompanyId(portletDataContext.getCompanyId());
      serviceContext.setSignedIn(false);
      serviceContext.setUserId(userId);

      ServiceContextThreadLocal.pushServiceContext(serviceContext);
    }

    // LAR validation

    validateFile(
        portletDataContext.getCompanyId(),
        portletDataContext.getGroupId(),
        portletDataContext.getPortletId(),
        portletDataContext.getZipReader());

    // Source and target group id

    Map<Long, Long> groupIds =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(Group.class);

    groupIds.put(portletDataContext.getSourceGroupId(), portletDataContext.getGroupId());

    // Manifest

    ManifestSummary manifestSummary = ExportImportHelperUtil.getManifestSummary(portletDataContext);

    if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
      PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
          "portlet", portletDataContext.getPortletId(), manifestSummary);
    }

    portletDataContext.setManifestSummary(manifestSummary);

    // Read expando tables, locks and permissions to make them
    // available to the data handlers through the portlet data context

    Element rootElement = portletDataContext.getImportDataRootElement();

    Element portletElement = null;

    try {
      portletElement = rootElement.element("portlet");

      Document portletDocument =
          SAXReaderUtil.read(
              portletDataContext.getZipEntryAsString(portletElement.attributeValue("path")));

      portletElement = portletDocument.getRootElement();
    } catch (DocumentException de) {
      throw new SystemException(de);
    }

    LayoutCache layoutCache = new LayoutCache();

    if (importPermissions) {
      _permissionImporter.checkRoles(
          layoutCache,
          portletDataContext.getCompanyId(),
          portletDataContext.getGroupId(),
          userId,
          portletElement);

      _permissionImporter.readPortletDataPermissions(portletDataContext);
    }

    readExpandoTables(portletDataContext);
    readLocks(portletDataContext);

    Element portletDataElement = portletElement.element("portlet-data");

    Map<String, Boolean> importPortletControlsMap =
        ExportImportHelperUtil.getImportPortletControlsMap(
            portletDataContext.getCompanyId(),
            portletDataContext.getPortletId(),
            parameterMap,
            portletDataElement,
            manifestSummary);

    Layout layout = LayoutLocalServiceUtil.getLayout(portletDataContext.getPlid());

    try {

      // Portlet preferences

      importPortletPreferences(
          portletDataContext,
          layout.getCompanyId(),
          portletDataContext.getGroupId(),
          layout,
          portletElement,
          true,
          importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
          importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_DATA),
          importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP),
          importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));

      // Portlet data

      if (importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_DATA)) {

        if (_log.isDebugEnabled()) {
          _log.debug("Importing portlet data");
        }

        importPortletData(portletDataContext, portletDataElement);
      }
    } finally {
      resetPortletScope(portletDataContext, portletDataContext.getGroupId());
    }

    // Portlet permissions

    if (importPermissions) {
      if (_log.isDebugEnabled()) {
        _log.debug("Importing portlet permissions");
      }

      _permissionImporter.importPortletPermissions(
          layoutCache,
          portletDataContext.getCompanyId(),
          portletDataContext.getGroupId(),
          userId,
          layout,
          portletElement,
          portletDataContext.getPortletId());

      if (userId > 0) {
        Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(User.class);

        User user = UserLocalServiceUtil.fetchUser(userId);

        indexer.reindex(user);
      }
    }

    // Asset links

    if (_log.isDebugEnabled()) {
      _log.debug("Importing asset links");
    }

    readAssetLinks(portletDataContext);

    // Deletion system events

    _deletionSystemEventImporter.importDeletionSystemEvents(portletDataContext);

    if (_log.isInfoEnabled()) {
      _log.info("Importing portlet takes " + stopWatch.getTime() + " ms");
    }

    // Service portlet preferences

    boolean importPortletSetup = importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP);

    if (importPortletSetup) {
      try {
        List<Element> serviceElements = rootElement.elements("service");

        for (Element serviceElement : serviceElements) {
          Document serviceDocument =
              SAXReaderUtil.read(
                  portletDataContext.getZipEntryAsString(serviceElement.attributeValue("path")));

          importServicePortletPreferences(portletDataContext, serviceDocument.getRootElement());
        }
      } catch (DocumentException de) {
        throw new SystemException(de);
      }
    }

    ZipReader zipReader = portletDataContext.getZipReader();

    zipReader.close();
  }