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