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