001
014
015 package com.liferay.portal.liveusers;
016
017 import com.liferay.portal.kernel.cluster.ClusterExecutorUtil;
018 import com.liferay.portal.kernel.cluster.ClusterNode;
019 import com.liferay.portal.kernel.concurrent.ConcurrentHashSet;
020 import com.liferay.portal.kernel.dao.orm.QueryUtil;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.servlet.PortalSessionContext;
024 import com.liferay.portal.kernel.util.Validator;
025 import com.liferay.portal.model.Group;
026 import com.liferay.portal.model.UserTracker;
027 import com.liferay.portal.service.GroupLocalServiceUtil;
028 import com.liferay.portal.service.UserTrackerLocalServiceUtil;
029 import com.liferay.portal.service.persistence.UserTrackerUtil;
030 import com.liferay.portal.util.PropsValues;
031
032 import java.util.ArrayList;
033 import java.util.Date;
034 import java.util.Iterator;
035 import java.util.LinkedHashMap;
036 import java.util.List;
037 import java.util.Map;
038 import java.util.Set;
039 import java.util.concurrent.ConcurrentHashMap;
040
041 import javax.servlet.http.HttpSession;
042
043
047 public class LiveUsers {
048
049 public static void addClusterNode(
050 String clusterNodeId, Map<Long, Map<Long, Set<String>>> clusterUsers) {
051
052 _instance._addClusterNode(clusterNodeId, clusterUsers);
053 }
054
055 public static void deleteGroup(long companyId, long groupId) {
056 _instance._deleteGroup(companyId, groupId);
057 }
058
059 public static Set<Long> getGroupUsers(long companyId, long groupId) {
060 return _instance._getGroupUsers(
061 _instance._getLiveUsers(companyId), groupId);
062 }
063
064 public static int getGroupUsersCount(long companyId, long groupId) {
065 return getGroupUsers(companyId, groupId).size();
066 }
067
068 public static Map<Long, Map<Long, Set<String>>> getLocalClusterUsers() {
069 return _instance._getLocalClusterUsers();
070 }
071
072 public static Map<String, UserTracker> getSessionUsers(long companyId) {
073 return _instance._getSessionUsers(companyId);
074 }
075
076 public static int getSessionUsersCount(long companyId) {
077 return getSessionUsers(companyId).size();
078 }
079
080
081
082
083
084 public static UserTracker getUserTracker(long companyId, String sessionId) {
085 return _instance._getUserTracker(companyId, sessionId);
086 }
087
088 public static void joinGroup(long companyId, long groupId, long userId) {
089 _instance._joinGroup(companyId, groupId, userId);
090 }
091
092 public static void joinGroup(long companyId, long groupId, long[] userIds) {
093 _instance._joinGroup(companyId, groupId, userIds);
094 }
095
096 public static void leaveGroup(long companyId, long groupId, long userId) {
097 _instance._leaveGroup(companyId, groupId, userId);
098 }
099
100 public static void leaveGroup(
101 long companyId, long groupId, long[] userIds) {
102
103 _instance._leaveGroup(companyId, groupId, userIds);
104 }
105
106 public static void removeClusterNode(String clusterNodeId) {
107 _instance._removeClusterNode(clusterNodeId);
108 }
109
110 public static void signIn(
111 String clusterNodeId, long companyId, long userId, String sessionId,
112 String remoteAddr, String remoteHost, String userAgent) {
113
114 _instance._signIn(
115 clusterNodeId, companyId, userId, sessionId, remoteAddr, remoteHost,
116 userAgent);
117 }
118
119 public static void signOut(
120 String clusterNodeId, long companyId, long userId, String sessionId) {
121
122 _instance._signOut(clusterNodeId, companyId, userId, sessionId);
123 }
124
125 private LiveUsers() {
126 }
127
128 private void _addClusterNode(
129 String clusterNodeId,
130 Map<Long, Map<Long, Set<String>>> clusterUsers) {
131
132 if (Validator.isNull(clusterNodeId)) {
133 return;
134 }
135
136 for (Map.Entry<Long, Map<Long, Set<String>>> companyUsers :
137 clusterUsers.entrySet()) {
138
139 long companyId = companyUsers.getKey();
140 Map<Long, Set<String>> userSessionsMap = companyUsers.getValue();
141
142 for (Map.Entry<Long, Set<String>> userSessions :
143 userSessionsMap.entrySet()) {
144
145 long userId = userSessions.getKey();
146
147 for (String sessionId : userSessions.getValue()) {
148 _signIn(
149 clusterNodeId, companyId, userId, sessionId, null, null,
150 null);
151 }
152 }
153 }
154 }
155
156 private void _addClusterUser(
157 String clusterNodeId, long companyId, long userId, String sessionId) {
158
159 if (Validator.isNull(clusterNodeId)) {
160 return;
161 }
162
163 Map<Long, Map<Long, Set<String>>> clusterUsers = _clusterUsers.get(
164 clusterNodeId);
165
166 if (clusterUsers == null) {
167 clusterUsers = new ConcurrentHashMap<>();
168
169 _clusterUsers.put(clusterNodeId, clusterUsers);
170 }
171
172 Map<Long, Set<String>> companyUsers = clusterUsers.get(companyId);
173
174 if (companyUsers == null) {
175 companyUsers = new ConcurrentHashMap<>();
176
177 clusterUsers.put(companyId, companyUsers);
178 }
179
180 Set<String> userSessions = companyUsers.get(userId);
181
182 if (userSessions == null) {
183 userSessions = new ConcurrentHashSet<>();
184
185 companyUsers.put(userId, userSessions);
186 }
187
188 userSessions.add(sessionId);
189 }
190
191 private void _addUserTracker(
192 long companyId, long userId, UserTracker userTracker) {
193
194 List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
195
196 if (userTrackers != null) {
197 userTrackers.add(userTracker);
198 }
199 else {
200 userTrackers = new ArrayList<>();
201
202 userTrackers.add(userTracker);
203
204 Map<Long, List<UserTracker>> userTrackersMap = _getUserTrackersMap(
205 companyId);
206
207 userTrackersMap.put(userId, userTrackers);
208 }
209 }
210
211 private void _deleteGroup(long companyId, long groupId) {
212 Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
213
214 liveUsers.remove(groupId);
215 }
216
217 private Set<Long> _getGroupUsers(
218 Map<Long, Set<Long>> liveUsers, long groupId) {
219
220 Set<Long> groupUsers = liveUsers.get(groupId);
221
222 if (groupUsers == null) {
223 groupUsers = new ConcurrentHashSet<>();
224
225 liveUsers.put(groupId, groupUsers);
226 }
227
228 return groupUsers;
229 }
230
231 private Map<Long, Set<Long>> _getLiveUsers(long companyId) {
232 Map<Long, Set<Long>> liveUsers = _liveUsers.get(companyId);
233
234 if (liveUsers == null) {
235 liveUsers = new ConcurrentHashMap<>();
236
237 _liveUsers.put(companyId, liveUsers);
238 }
239
240 return liveUsers;
241 }
242
243 private Map<Long, Map<Long, Set<String>>> _getLocalClusterUsers() {
244 ClusterNode clusterNode = ClusterExecutorUtil.getLocalClusterNode();
245
246 if (clusterNode == null) {
247 return null;
248 }
249
250 return _clusterUsers.get(clusterNode.getClusterNodeId());
251 }
252
253 private Map<String, UserTracker> _getSessionUsers(long companyId) {
254 Map<String, UserTracker> sessionUsers = _sessionUsers.get(companyId);
255
256 if (sessionUsers == null) {
257 sessionUsers = new ConcurrentHashMap<>();
258
259 _sessionUsers.put(companyId, sessionUsers);
260 }
261
262 return sessionUsers;
263 }
264
265 private UserTracker _getUserTracker(long companyId, String sessionId) {
266 Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
267
268 return sessionUsers.get(sessionId);
269 }
270
271 private List<UserTracker> _getUserTrackers(long companyId, long userId) {
272 Map<Long, List<UserTracker>> userTrackersMap = _getUserTrackersMap(
273 companyId);
274
275 return userTrackersMap.get(userId);
276 }
277
278 private Map<Long, List<UserTracker>> _getUserTrackersMap(long companyId) {
279 Map<Long, List<UserTracker>> userTrackersMap = _userTrackers.get(
280 companyId);
281
282 if (userTrackersMap == null) {
283 userTrackersMap = new ConcurrentHashMap<>();
284
285 _userTrackers.put(companyId, userTrackersMap);
286 }
287
288 return userTrackersMap;
289 }
290
291 private void _joinGroup(long companyId, long groupId, long userId) {
292 Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
293
294 Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
295
296 if (_getUserTrackers(companyId, userId) != null) {
297 groupUsers.add(userId);
298 }
299 }
300
301 private void _joinGroup(long companyId, long groupId, long[] userIds) {
302 Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
303
304 Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
305
306 for (long userId : userIds) {
307 if (_getUserTrackers(companyId, userId) != null) {
308 groupUsers.add(userId);
309 }
310 }
311 }
312
313 private void _leaveGroup(long companyId, long userId, long groupId) {
314 Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
315
316 Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
317
318 groupUsers.remove(userId);
319 }
320
321 private void _leaveGroup(long companyId, long groupId, long[] userIds) {
322 Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
323
324 Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
325
326 for (long userId : userIds) {
327 groupUsers.remove(userId);
328 }
329 }
330
331 private void _removeClusterNode(String clusterNodeId) {
332 if (Validator.isNull(clusterNodeId)) {
333 return;
334 }
335
336 Map<Long, Map<Long, Set<String>>> clusterUsers = _clusterUsers.remove(
337 clusterNodeId);
338
339 if (clusterUsers == null) {
340 return;
341 }
342
343 for (Map.Entry<Long, Map<Long, Set<String>>> companyUsers :
344 clusterUsers.entrySet()) {
345
346 long companyId = companyUsers.getKey();
347 Map<Long, Set<String>> userSessionsMap = companyUsers.getValue();
348
349 for (Map.Entry<Long, Set<String>> userSessions :
350 userSessionsMap.entrySet()) {
351
352 long userId = userSessions.getKey();
353
354 for (String sessionId : userSessions.getValue()) {
355 _signOut(clusterNodeId, companyId, userId, sessionId);
356 }
357 }
358 }
359 }
360
361 private void _removeClusterUser(
362 String clusterNodeId, long companyId, long userId, String sessionId) {
363
364 if (Validator.isNull(clusterNodeId)) {
365 return;
366 }
367
368 Map<Long, Map<Long, Set<String>>> clusterUsers = _clusterUsers.get(
369 clusterNodeId);
370
371 if (clusterUsers == null) {
372 return;
373 }
374
375 Map<Long, Set<String>> companyUsers = clusterUsers.get(companyId);
376
377 if (companyUsers == null) {
378 return;
379 }
380
381 Set<String> userSessions = companyUsers.get(userId);
382
383 if (userSessions == null) {
384 return;
385 }
386
387 userSessions.remove(sessionId);
388 }
389
390 private void _removeUserTracker(
391 long companyId, long userId, UserTracker userTracker) {
392
393 List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
394
395 if (userTrackers == null) {
396 return;
397 }
398
399 String sessionId = userTracker.getSessionId();
400
401 Iterator<UserTracker> itr = userTrackers.iterator();
402
403 while (itr.hasNext()) {
404 UserTracker curUserTracker = itr.next();
405
406 if (sessionId.equals(curUserTracker.getSessionId())) {
407 itr.remove();
408 }
409 }
410
411 if (userTrackers.isEmpty()) {
412 Map<Long, List<UserTracker>> userTrackersMap = _getUserTrackersMap(
413 companyId);
414
415 userTrackersMap.remove(userId);
416 }
417 }
418
419 private void _signIn(
420 String clusterNodeId, long companyId, long userId, String sessionId,
421 String remoteAddr, String remoteHost, String userAgent) {
422
423 _addClusterUser(clusterNodeId, companyId, userId, sessionId);
424
425 _updateGroupStatus(companyId, userId, true);
426
427 Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
428
429 UserTracker userTracker = sessionUsers.get(sessionId);
430
431
432
433
434
435
436
437
438
439
440
441 if ((userTracker == null) &&
442 PropsValues.SESSION_TRACKER_MEMORY_ENABLED) {
443
444 userTracker = UserTrackerUtil.create(0);
445
446 userTracker.setCompanyId(companyId);
447 userTracker.setUserId(userId);
448 userTracker.setModifiedDate(new Date());
449 userTracker.setSessionId(sessionId);
450 userTracker.setRemoteAddr(remoteAddr);
451 userTracker.setRemoteHost(remoteHost);
452 userTracker.setUserAgent(userAgent);
453
454 sessionUsers.put(sessionId, userTracker);
455
456 _addUserTracker(companyId, userId, userTracker);
457 }
458 }
459
460 private void _signOut(
461 String clusterNodeId, long companyId, long userId, String sessionId) {
462
463 _removeClusterUser(clusterNodeId, companyId, userId, sessionId);
464
465 List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
466
467 if ((userTrackers == null) || (userTrackers.size() <= 1)) {
468 _updateGroupStatus(companyId, userId, false);
469 }
470
471 Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
472
473 UserTracker userTracker = sessionUsers.remove(sessionId);
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489 if (userTracker == null) {
490 return;
491 }
492
493 try {
494 UserTrackerLocalServiceUtil.addUserTracker(
495 userTracker.getCompanyId(), userTracker.getUserId(),
496 userTracker.getModifiedDate(), sessionId,
497 userTracker.getRemoteAddr(), userTracker.getRemoteHost(),
498 userTracker.getUserAgent(), userTracker.getPaths());
499 }
500 catch (Exception e) {
501 if (_log.isWarnEnabled()) {
502 _log.warn(e.getMessage());
503 }
504 }
505
506 try {
507 HttpSession session = PortalSessionContext.get(sessionId);
508
509 if (session != null) {
510 session.invalidate();
511 }
512 }
513 catch (Exception e) {
514 }
515
516 _removeUserTracker(companyId, userId, userTracker);
517 }
518
519 private Map<Long, Set<Long>> _updateGroupStatus(
520 long companyId, long userId, boolean signedIn) {
521
522 Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
523
524 LinkedHashMap<String, Object> groupParams = new LinkedHashMap<>();
525
526 groupParams.put("usersGroups", userId);
527
528 List<Group> groups = GroupLocalServiceUtil.search(
529 companyId, null, null, groupParams, QueryUtil.ALL_POS,
530 QueryUtil.ALL_POS);
531
532 for (Group group : groups) {
533 Set<Long> groupUsers = _getGroupUsers(
534 liveUsers, group.getGroupId());
535
536 if (signedIn) {
537 groupUsers.add(userId);
538 }
539 else {
540 groupUsers.remove(userId);
541 }
542 }
543
544 return liveUsers;
545 }
546
547 private static final Log _log = LogFactoryUtil.getLog(LiveUsers.class);
548
549 private static final LiveUsers _instance = new LiveUsers();
550
551
552
553 private final Map<String, Map<Long, Map<Long, Set<String>>>> _clusterUsers =
554 new ConcurrentHashMap<>();
555 private final Map<Long, Map<Long, Set<Long>>> _liveUsers =
556 new ConcurrentHashMap<>();
557 private final Map<Long, Map<String, UserTracker>> _sessionUsers =
558 new ConcurrentHashMap<>();
559 private final Map<Long, Map<Long, List<UserTracker>>> _userTrackers =
560 new ConcurrentHashMap<>();
561
562 }