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