All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.portal.liveusers.LiveUsers Maven / Gradle / Ivy

/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.liveusers;

import com.liferay.portal.kernel.cluster.ClusterExecutorUtil;
import com.liferay.portal.kernel.cluster.ClusterMasterExecutorUtil;
import com.liferay.portal.kernel.cluster.ClusterNode;
import com.liferay.portal.kernel.dao.orm.QueryUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.Group;
import com.liferay.portal.kernel.model.UserTracker;
import com.liferay.portal.kernel.service.GroupLocalServiceUtil;
import com.liferay.portal.kernel.service.UserTrackerLocalServiceUtil;
import com.liferay.portal.kernel.service.persistence.UserTrackerUtil;
import com.liferay.portal.kernel.servlet.PortalSessionContext;
import com.liferay.portal.kernel.util.LinkedHashMapBuilder;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.util.PropsValues;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpSession;

/**
 * @author Charles May
 * @author Brian Wing Shun Chan
 */
public class LiveUsers {

	public static void addClusterNode(
		String clusterNodeId, Map>> clusterUsers) {

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

		for (Map.Entry>> companyUsers :
				clusterUsers.entrySet()) {

			long companyId = companyUsers.getKey();
			Map> userSessionsMap = companyUsers.getValue();

			for (Map.Entry> userSessions :
					userSessionsMap.entrySet()) {

				long userId = userSessions.getKey();

				for (String sessionId : userSessions.getValue()) {
					signIn(
						clusterNodeId, companyId, userId, sessionId, null, null,
						null);
				}
			}
		}
	}

	public static void deleteGroup(long companyId, long groupId) {
		Map> liveUsers = _getLiveUsers(companyId);

		liveUsers.remove(groupId);
	}

	public static Set getGroupUsers(long companyId, long groupId) {
		return _getGroupUsers(_getLiveUsers(companyId), groupId);
	}

	public static int getGroupUsersCount(long companyId, long groupId) {
		Set groupUsers = getGroupUsers(companyId, groupId);

		return groupUsers.size();
	}

	public static Map>> getLocalClusterUsers() {
		ClusterNode clusterNode = ClusterExecutorUtil.getLocalClusterNode();

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

		return _clusterUsers.get(clusterNode.getClusterNodeId());
	}

	public static Map getSessionUsers(long companyId) {
		Map sessionUsers = _sessionUsers.get(companyId);

		if (sessionUsers == null) {
			sessionUsers = new ConcurrentHashMap<>();

			_sessionUsers.put(companyId, sessionUsers);
		}

		return sessionUsers;
	}

	public static int getSessionUsersCount(long companyId) {
		Map sessionUsers = getSessionUsers(companyId);

		return sessionUsers.size();
	}

	public static UserTracker getUserTracker(long companyId, String sessionId) {
		Map sessionUsers = getSessionUsers(companyId);

		return sessionUsers.get(sessionId);
	}

	public static void joinGroup(long companyId, long groupId, long userId) {
		Map> liveUsers = _getLiveUsers(companyId);

		if (_getUserTrackers(companyId, userId) != null) {
			Set groupUsers = _getGroupUsers(liveUsers, groupId);

			groupUsers.add(userId);
		}
	}

	public static void joinGroup(long companyId, long groupId, long[] userIds) {
		Set groupUsers = _getGroupUsers(
			_getLiveUsers(companyId), groupId);

		for (long userId : userIds) {
			if (_getUserTrackers(companyId, userId) != null) {
				groupUsers.add(userId);
			}
		}
	}

	public static void leaveGroup(long companyId, long groupId, long userId) {
		Set groupUsers = _getGroupUsers(
			_getLiveUsers(companyId), groupId);

		groupUsers.remove(userId);
	}

	public static void leaveGroup(
		long companyId, long groupId, long[] userIds) {

		Set groupUsers = _getGroupUsers(
			_getLiveUsers(companyId), groupId);

		for (long userId : userIds) {
			groupUsers.remove(userId);
		}
	}

	public static void removeClusterNode(String clusterNodeId) {
		if (Validator.isNull(clusterNodeId)) {
			return;
		}

		Map>> clusterUsers = _clusterUsers.remove(
			clusterNodeId);

		if (clusterUsers == null) {
			return;
		}

		for (Map.Entry>> companyUsers :
				clusterUsers.entrySet()) {

			long companyId = companyUsers.getKey();
			Map> userSessionsMap = companyUsers.getValue();

			for (Map.Entry> userSessions :
					userSessionsMap.entrySet()) {

				long userId = userSessions.getKey();

				for (String sessionId : userSessions.getValue()) {
					signOut(clusterNodeId, companyId, userId, sessionId);
				}
			}
		}
	}

	public static void signIn(
		String clusterNodeId, long companyId, long userId, String sessionId,
		String remoteAddr, String remoteHost, String userAgent) {

		_addClusterUser(clusterNodeId, companyId, userId, sessionId);

		_updateGroupStatus(companyId, userId, true);

		Map sessionUsers = getSessionUsers(companyId);

		UserTracker userTracker = sessionUsers.get(sessionId);

		if ((userTracker == null) &&
			PropsValues.SESSION_TRACKER_MEMORY_ENABLED) {

			userTracker = UserTrackerUtil.create(0);

			userTracker.setCompanyId(companyId);
			userTracker.setUserId(userId);
			userTracker.setModifiedDate(new Date());
			userTracker.setSessionId(sessionId);
			userTracker.setRemoteAddr(remoteAddr);
			userTracker.setRemoteHost(remoteHost);
			userTracker.setUserAgent(userAgent);

			sessionUsers.put(sessionId, userTracker);

			_addUserTracker(companyId, userId, userTracker);
		}
	}

	public static void signOut(
		String clusterNodeId, long companyId, long userId, String sessionId) {

		_removeClusterUser(clusterNodeId, companyId, userId, sessionId);

		List userTrackers = _getUserTrackers(companyId, userId);

		if ((userTrackers == null) || (userTrackers.size() <= 1)) {
			_updateGroupStatus(companyId, userId, false);
		}

		Map sessionUsers = getSessionUsers(companyId);

		UserTracker userTracker = sessionUsers.remove(sessionId);

		if (userTracker == null) {
			return;
		}

		try {
			if (ClusterMasterExecutorUtil.isMaster()) {
				UserTrackerLocalServiceUtil.addUserTracker(
					userTracker.getCompanyId(), userTracker.getUserId(),
					userTracker.getModifiedDate(), sessionId,
					userTracker.getRemoteAddr(), userTracker.getRemoteHost(),
					userTracker.getUserAgent(), userTracker.getPaths());
			}
		}
		catch (Exception exception) {
			if (_log.isWarnEnabled()) {
				_log.warn(exception);
			}
		}

		try {
			HttpSession httpSession = PortalSessionContext.get(sessionId);

			if (httpSession != null) {
				httpSession.invalidate();
			}
		}
		catch (Exception exception) {
			if (_log.isDebugEnabled()) {
				_log.debug(exception);
			}
		}

		_removeUserTracker(companyId, userId, userTracker);
	}

	private static void _addClusterUser(
		String clusterNodeId, long companyId, long userId, String sessionId) {

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

		Map>> clusterUsers = _clusterUsers.get(
			clusterNodeId);

		if (clusterUsers == null) {
			clusterUsers = new ConcurrentHashMap<>();

			_clusterUsers.put(clusterNodeId, clusterUsers);
		}

		Map> companyUsers = clusterUsers.get(companyId);

		if (companyUsers == null) {
			companyUsers = new ConcurrentHashMap<>();

			clusterUsers.put(companyId, companyUsers);
		}

		Set userSessions = companyUsers.get(userId);

		if (userSessions == null) {
			userSessions = Collections.newSetFromMap(new ConcurrentHashMap<>());

			companyUsers.put(userId, userSessions);
		}

		userSessions.add(sessionId);
	}

	private static void _addUserTracker(
		long companyId, long userId, UserTracker userTracker) {

		List userTrackers = _getUserTrackers(companyId, userId);

		if (userTrackers != null) {
			userTrackers.add(userTracker);
		}
		else {
			userTrackers = new ArrayList<>();

			userTrackers.add(userTracker);

			Map> userTrackersMap = _getUserTrackersMap(
				companyId);

			userTrackersMap.put(userId, userTrackers);
		}
	}

	private static Set _getGroupUsers(
		Map> liveUsers, long groupId) {

		Set groupUsers = liveUsers.get(groupId);

		if (groupUsers == null) {
			groupUsers = Collections.newSetFromMap(new ConcurrentHashMap<>());

			liveUsers.put(groupId, groupUsers);
		}

		return groupUsers;
	}

	private static Map> _getLiveUsers(long companyId) {
		Map> liveUsers = _liveUsers.get(companyId);

		if (liveUsers == null) {
			liveUsers = new ConcurrentHashMap<>();

			_liveUsers.put(companyId, liveUsers);
		}

		return liveUsers;
	}

	private static List _getUserTrackers(
		long companyId, long userId) {

		Map> userTrackersMap = _getUserTrackersMap(
			companyId);

		return userTrackersMap.get(userId);
	}

	private static Map> _getUserTrackersMap(
		long companyId) {

		Map> userTrackersMap = _userTrackers.get(
			companyId);

		if (userTrackersMap == null) {
			userTrackersMap = new ConcurrentHashMap<>();

			_userTrackers.put(companyId, userTrackersMap);
		}

		return userTrackersMap;
	}

	private static void _removeClusterUser(
		String clusterNodeId, long companyId, long userId, String sessionId) {

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

		Map>> clusterUsers = _clusterUsers.get(
			clusterNodeId);

		if (clusterUsers == null) {
			return;
		}

		Map> companyUsers = clusterUsers.get(companyId);

		if (companyUsers == null) {
			return;
		}

		Set userSessions = companyUsers.get(userId);

		if (userSessions == null) {
			return;
		}

		userSessions.remove(sessionId);
	}

	private static void _removeUserTracker(
		long companyId, long userId, UserTracker userTracker) {

		List userTrackers = _getUserTrackers(companyId, userId);

		if (userTrackers == null) {
			return;
		}

		String sessionId = userTracker.getSessionId();

		Iterator iterator = userTrackers.iterator();

		while (iterator.hasNext()) {
			UserTracker curUserTracker = iterator.next();

			if (sessionId.equals(curUserTracker.getSessionId())) {
				iterator.remove();
			}
		}

		if (userTrackers.isEmpty()) {
			Map> userTrackersMap = _getUserTrackersMap(
				companyId);

			userTrackersMap.remove(userId);
		}
	}

	private static Map> _updateGroupStatus(
		long companyId, long userId, boolean signedIn) {

		Map> liveUsers = _getLiveUsers(companyId);

		List groups = GroupLocalServiceUtil.search(
			companyId, null, null,
			LinkedHashMapBuilder.put(
				"usersGroups", userId
			).build(),
			QueryUtil.ALL_POS, QueryUtil.ALL_POS);

		for (Group group : groups) {
			Set groupUsers = _getGroupUsers(
				liveUsers, group.getGroupId());

			if (signedIn) {
				groupUsers.add(userId);
			}
			else {
				groupUsers.remove(userId);
			}
		}

		return liveUsers;
	}

	private LiveUsers() {
	}

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

	private static final Map>>>
		_clusterUsers = new ConcurrentHashMap<>();
	private static final Map>> _liveUsers =
		new ConcurrentHashMap<>();
	private static final Map> _sessionUsers =
		new ConcurrentHashMap<>();
	private static final Map>> _userTrackers =
		new ConcurrentHashMap<>();

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy