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 =
168 new ConcurrentHashMap<Long, Map<Long, Set<String>>>();
169
170 _clusterUsers.put(clusterNodeId, clusterUsers);
171 }
172
173 Map<Long, Set<String>> companyUsers = clusterUsers.get(companyId);
174
175 if (companyUsers == null) {
176 companyUsers = new ConcurrentHashMap<Long, Set<String>>();
177
178 clusterUsers.put(companyId, companyUsers);
179 }
180
181 Set<String> userSessions = companyUsers.get(userId);
182
183 if (userSessions == null) {
184 userSessions = new ConcurrentHashSet<String>();
185
186 companyUsers.put(userId, userSessions);
187 }
188
189 userSessions.add(sessionId);
190 }
191
192 private void _addUserTracker(
193 long companyId, long userId, UserTracker userTracker) {
194
195 List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
196
197 if (userTrackers != null) {
198 userTrackers.add(userTracker);
199 }
200 else {
201 userTrackers = new ArrayList<UserTracker>();
202
203 userTrackers.add(userTracker);
204
205 Map<Long, List<UserTracker>> userTrackersMap = _getUserTrackersMap(
206 companyId);
207
208 userTrackersMap.put(userId, userTrackers);
209 }
210 }
211
212 private void _deleteGroup(long companyId, long groupId) {
213 Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
214
215 liveUsers.remove(groupId);
216 }
217
218 private Set<Long> _getGroupUsers(
219 Map<Long, Set<Long>> liveUsers, long groupId) {
220
221 Set<Long> groupUsers = liveUsers.get(groupId);
222
223 if (groupUsers == null) {
224 groupUsers = new ConcurrentHashSet<Long>();
225
226 liveUsers.put(groupId, groupUsers);
227 }
228
229 return groupUsers;
230 }
231
232 private Map<Long, Set<Long>> _getLiveUsers(long companyId) {
233 Map<Long, Set<Long>> liveUsers = _liveUsers.get(companyId);
234
235 if (liveUsers == null) {
236 liveUsers = new ConcurrentHashMap<Long, Set<Long>>();
237
238 _liveUsers.put(companyId, liveUsers);
239 }
240
241 return liveUsers;
242 }
243
244 private Map<Long, Map<Long, Set<String>>> _getLocalClusterUsers() {
245 ClusterNode clusterNode = ClusterExecutorUtil.getLocalClusterNode();
246
247 if (clusterNode == null) {
248 return null;
249 }
250
251 return _clusterUsers.get(clusterNode.getClusterNodeId());
252 }
253
254 private Map<String, UserTracker> _getSessionUsers(long companyId) {
255 Map<String, UserTracker> sessionUsers = _sessionUsers.get(companyId);
256
257 if (sessionUsers == null) {
258 sessionUsers = new ConcurrentHashMap<String, UserTracker>();
259
260 _sessionUsers.put(companyId, sessionUsers);
261 }
262
263 return sessionUsers;
264 }
265
266 private UserTracker _getUserTracker(long companyId, String sessionId) {
267 Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
268
269 return sessionUsers.get(sessionId);
270 }
271
272 private List<UserTracker> _getUserTrackers(long companyId, long userId) {
273 Map<Long, List<UserTracker>> userTrackersMap = _getUserTrackersMap(
274 companyId);
275
276 return userTrackersMap.get(userId);
277 }
278
279 private Map<Long, List<UserTracker>> _getUserTrackersMap(long companyId) {
280 Map<Long, List<UserTracker>> userTrackersMap = _userTrackers.get(
281 companyId);
282
283 if (userTrackersMap == null) {
284 userTrackersMap = new ConcurrentHashMap<Long, List<UserTracker>>();
285
286 _userTrackers.put(companyId, userTrackersMap);
287 }
288
289 return userTrackersMap;
290 }
291
292 private void _joinGroup(long companyId, long groupId, long userId) {
293 Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
294
295 Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
296
297 if (_getUserTrackers(companyId, userId) != null) {
298 groupUsers.add(userId);
299 }
300 }
301
302 private void _joinGroup(long companyId, long groupId, long[] userIds) {
303 Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
304
305 Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
306
307 for (long userId : userIds) {
308 if (_getUserTrackers(companyId, userId) != null) {
309 groupUsers.add(userId);
310 }
311 }
312 }
313
314 private void _leaveGroup(long companyId, long userId, long groupId) {
315 Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
316
317 Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
318
319 groupUsers.remove(userId);
320 }
321
322 private void _leaveGroup(long companyId, long groupId, long[] userIds) {
323 Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
324
325 Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
326
327 for (long userId : userIds) {
328 groupUsers.remove(userId);
329 }
330 }
331
332 private void _removeClusterNode(String clusterNodeId) {
333 if (Validator.isNull(clusterNodeId)) {
334 return;
335 }
336
337 Map<Long, Map<Long, Set<String>>> clusterUsers = _clusterUsers.remove(
338 clusterNodeId);
339
340 if (clusterUsers == null) {
341 return;
342 }
343
344 for (Map.Entry<Long, Map<Long, Set<String>>> companyUsers :
345 clusterUsers.entrySet()) {
346
347 long companyId = companyUsers.getKey();
348 Map<Long, Set<String>> userSessionsMap = companyUsers.getValue();
349
350 for (Map.Entry<Long, Set<String>> userSessions :
351 userSessionsMap.entrySet()) {
352
353 long userId = userSessions.getKey();
354
355 for (String sessionId : userSessions.getValue()) {
356 _signOut(clusterNodeId, companyId, userId, sessionId);
357 }
358 }
359 }
360 }
361
362 private void _removeClusterUser(
363 String clusterNodeId, long companyId, long userId, String sessionId) {
364
365 if (Validator.isNull(clusterNodeId)) {
366 return;
367 }
368
369 Map<Long, Map<Long, Set<String>>> clusterUsers = _clusterUsers.get(
370 clusterNodeId);
371
372 if (clusterUsers == null) {
373 return;
374 }
375
376 Map<Long, Set<String>> companyUsers = clusterUsers.get(companyId);
377
378 if (companyUsers == null) {
379 return;
380 }
381
382 Set<String> userSessions = companyUsers.get(userId);
383
384 if (userSessions == null) {
385 return;
386 }
387
388 userSessions.remove(sessionId);
389 }
390
391 private void _removeUserTracker(
392 long companyId, long userId, UserTracker userTracker) {
393
394 List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
395
396 if (userTrackers == null) {
397 return;
398 }
399
400 String sessionId = userTracker.getSessionId();
401
402 Iterator<UserTracker> itr = userTrackers.iterator();
403
404 while (itr.hasNext()) {
405 UserTracker curUserTracker = itr.next();
406
407 if (sessionId.equals(curUserTracker.getSessionId())) {
408 itr.remove();
409 }
410 }
411
412 if (userTrackers.isEmpty()) {
413 Map<Long, List<UserTracker>> userTrackersMap = _getUserTrackersMap(
414 companyId);
415
416 userTrackersMap.remove(userId);
417 }
418 }
419
420 private void _signIn(
421 String clusterNodeId, long companyId, long userId, String sessionId,
422 String remoteAddr, String remoteHost, String userAgent) {
423
424 _addClusterUser(clusterNodeId, companyId, userId, sessionId);
425
426 _updateGroupStatus(companyId, userId, true);
427
428 Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
429
430 UserTracker userTracker = sessionUsers.get(sessionId);
431
432
433
434
435
436
437
438
439
440
441
442 if ((userTracker == null) &&
443 PropsValues.SESSION_TRACKER_MEMORY_ENABLED) {
444
445 userTracker = UserTrackerUtil.create(0);
446
447 userTracker.setCompanyId(companyId);
448 userTracker.setUserId(userId);
449 userTracker.setModifiedDate(new Date());
450 userTracker.setSessionId(sessionId);
451 userTracker.setRemoteAddr(remoteAddr);
452 userTracker.setRemoteHost(remoteHost);
453 userTracker.setUserAgent(userAgent);
454
455 sessionUsers.put(sessionId, userTracker);
456
457 _addUserTracker(companyId, userId, userTracker);
458 }
459 }
460
461 private void _signOut(
462 String clusterNodeId, long companyId, long userId, String sessionId) {
463
464 _removeClusterUser(clusterNodeId, companyId, userId, sessionId);
465
466 List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
467
468 if ((userTrackers == null) || (userTrackers.size() <= 1)) {
469 _updateGroupStatus(companyId, userId, false);
470 }
471
472 Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
473
474 UserTracker userTracker = sessionUsers.remove(sessionId);
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490 if (userTracker == null) {
491 return;
492 }
493
494 try {
495 UserTrackerLocalServiceUtil.addUserTracker(
496 userTracker.getCompanyId(), userTracker.getUserId(),
497 userTracker.getModifiedDate(), sessionId,
498 userTracker.getRemoteAddr(), userTracker.getRemoteHost(),
499 userTracker.getUserAgent(), userTracker.getPaths());
500 }
501 catch (Exception e) {
502 if (_log.isWarnEnabled()) {
503 _log.warn(e.getMessage());
504 }
505 }
506
507 try {
508 HttpSession session = PortalSessionContext.get(sessionId);
509
510 if (session != null) {
511 session.invalidate();
512 }
513 }
514 catch (Exception e) {
515 }
516
517 _removeUserTracker(companyId, userId, userTracker);
518 }
519
520 private Map<Long, Set<Long>> _updateGroupStatus(
521 long companyId, long userId, boolean signedIn) {
522
523 Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
524
525 LinkedHashMap<String, Object> groupParams =
526 new LinkedHashMap<String, Object>();
527
528 groupParams.put("usersGroups", userId);
529
530 List<Group> groups = GroupLocalServiceUtil.search(
531 companyId, null, null, groupParams, QueryUtil.ALL_POS,
532 QueryUtil.ALL_POS);
533
534 for (Group group : groups) {
535 Set<Long> groupUsers = _getGroupUsers(
536 liveUsers, group.getGroupId());
537
538 if (signedIn) {
539 groupUsers.add(userId);
540 }
541 else {
542 groupUsers.remove(userId);
543 }
544 }
545
546 return liveUsers;
547 }
548
549 private static final Log _log = LogFactoryUtil.getLog(LiveUsers.class);
550
551 private static final LiveUsers _instance = new LiveUsers();
552
553
554
555 private final Map<String, Map<Long, Map<Long, Set<String>>>> _clusterUsers =
556 new ConcurrentHashMap<String, Map<Long, Map<Long, Set<String>>>>();
557 private final Map<Long, Map<Long, Set<Long>>> _liveUsers =
558 new ConcurrentHashMap<Long, Map<Long, Set<Long>>>();
559 private final Map<Long, Map<String, UserTracker>> _sessionUsers =
560 new ConcurrentHashMap<Long, Map<String, UserTracker>>();
561 private final Map<Long, Map<Long, List<UserTracker>>> _userTrackers =
562 new ConcurrentHashMap<Long, Map<Long, List<UserTracker>>>();
563
564 }