001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.liveusers;
016    
017    import com.liferay.portal.kernel.dao.orm.QueryUtil;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.util.ConcurrentHashSet;
022    import com.liferay.portal.model.Group;
023    import com.liferay.portal.model.UserTracker;
024    import com.liferay.portal.service.GroupLocalServiceUtil;
025    import com.liferay.portal.service.UserTrackerLocalServiceUtil;
026    import com.liferay.portal.service.persistence.UserTrackerUtil;
027    import com.liferay.portal.util.PropsValues;
028    import com.liferay.portal.util.WebAppPool;
029    import com.liferay.portal.util.WebKeys;
030    
031    import java.util.ArrayList;
032    import java.util.Date;
033    import java.util.Iterator;
034    import java.util.LinkedHashMap;
035    import java.util.List;
036    import java.util.Map;
037    import java.util.Set;
038    import java.util.concurrent.ConcurrentHashMap;
039    
040    /**
041     * @author Charles May
042     * @author Brian Wing Shun Chan
043     */
044    public class LiveUsers {
045    
046            public static void deleteGroup(long companyId, long groupId) {
047                    _instance._deleteGroup(companyId, groupId);
048            }
049    
050            public static Set<Long> getGroupUsers(long companyId, long groupId) {
051                    return _instance._getGroupUsers(
052                            _instance._getLiveUsers(companyId), groupId);
053            }
054    
055            public static int getGroupUsersCount(long companyId, long groupId) {
056                    return getGroupUsers(companyId, groupId).size();
057            }
058    
059            public static Map<String, UserTracker> getSessionUsers(long companyId) {
060                    return _instance._getSessionUsers(companyId);
061            }
062    
063            public static int getSessionUsersCount(long companyId) {
064                    return getSessionUsers(companyId).size();
065            }
066    
067            public static UserTracker getUserTracker(long companyId, String sessionId) {
068                    return _instance._getUserTracker(companyId, sessionId);
069            }
070    
071            public static void joinGroup(long companyId, long groupId, long userId) {
072                    _instance._joinGroup(companyId, groupId, userId);
073            }
074    
075            public static void joinGroup(long companyId, long groupId, long[] userIds) {
076                    _instance._joinGroup(companyId, groupId, userIds);
077            }
078    
079            public static void leaveGroup(long companyId, long groupId, long userId) {
080                    _instance._leaveGroup(companyId, groupId, userId);
081            }
082    
083            public static void leaveGroup(
084                    long companyId, long groupId, long[] userIds) {
085    
086                    _instance._leaveGroup(companyId, groupId, userIds);
087            }
088    
089            public static void signIn(
090                            long companyId, long userId, String sessionId, String remoteAddr,
091                            String remoteHost, String userAgent)
092                    throws SystemException {
093    
094                    _instance._signIn(
095                            companyId, userId, sessionId, remoteAddr, remoteHost, userAgent);
096            }
097    
098            public static void signOut(long companyId, long userId, String sessionId)
099                    throws SystemException {
100    
101                    _instance._signOut(companyId, userId, sessionId);
102            }
103    
104            private LiveUsers() {
105            }
106    
107            private void _addUserTracker(
108                    long companyId, long userId, UserTracker userTracker) {
109    
110                    List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
111    
112                    if (userTrackers != null) {
113                            userTrackers.add(userTracker);
114                    }
115                    else {
116                            userTrackers = new ArrayList<UserTracker>();
117    
118                            userTrackers.add(userTracker);
119    
120                            Map<Long, List<UserTracker>> userTrackersMap =
121                                    _getUserTrackersMap(companyId);
122    
123                            userTrackersMap.put(userId, userTrackers);
124                    }
125            }
126    
127            private void _deleteGroup(long companyId, long groupId) {
128                    Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
129    
130                    liveUsers.remove(groupId);
131            }
132    
133            private Set<Long> _getGroupUsers(
134                    Map<Long, Set<Long>> liveUsers, long groupId) {
135    
136                    Set<Long> groupUsers = liveUsers.get(groupId);
137    
138                    if (groupUsers == null) {
139                            groupUsers = new ConcurrentHashSet<Long>();
140    
141                            liveUsers.put(groupId, groupUsers);
142                    }
143    
144                    return groupUsers;
145            }
146    
147            private Map<Long, Set<Long>> _getLiveUsers(long companyId) {
148                    String companyIdString = String.valueOf(companyId);
149    
150                    Map<Long, Set<Long>> liveUsers = (Map<Long, Set<Long>>)WebAppPool.get(
151                            companyIdString, WebKeys.LIVE_USERS);
152    
153                    if (liveUsers == null) {
154                            liveUsers = new ConcurrentHashMap<Long, Set<Long>>();
155    
156                            WebAppPool.put(companyIdString, WebKeys.LIVE_USERS, liveUsers);
157                    }
158    
159                    return liveUsers;
160            }
161    
162            private Map<String, UserTracker> _getSessionUsers(long companyId) {
163                    String companyIdString = String.valueOf(companyId);
164    
165                    Map<String, UserTracker> sessionUsers =
166                            (Map<String, UserTracker>)WebAppPool.get(
167                                    companyIdString, WebKeys.LIVE_SESSION_USERS);
168    
169                    if (sessionUsers == null) {
170                            sessionUsers = new ConcurrentHashMap<String, UserTracker>();
171    
172                            WebAppPool.put(
173                                    companyIdString, WebKeys.LIVE_SESSION_USERS, sessionUsers);
174                    }
175    
176                    return sessionUsers;
177            }
178    
179            private UserTracker _getUserTracker(long companyId, String sessionId) {
180                    Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
181    
182                    return sessionUsers.get(sessionId);
183            }
184    
185            private List<UserTracker> _getUserTrackers(long companyId, long userId) {
186                    Map<Long, List<UserTracker>> userTrackersMap = _getUserTrackersMap(
187                            companyId);
188    
189                    return userTrackersMap.get(userId);
190            }
191    
192            private Map<Long, List<UserTracker>> _getUserTrackersMap(long companyId) {
193                    String companyIdString = String.valueOf(companyId);
194    
195                    Map<Long, List<UserTracker>> userTrackersMap =
196                            (Map<Long, List<UserTracker>>)WebAppPool.get(
197                                    companyIdString, WebKeys.LIVE_USER_TRACKERS);
198    
199                    if (userTrackersMap == null) {
200                            userTrackersMap = new ConcurrentHashMap<Long, List<UserTracker>>();
201    
202                            WebAppPool.put(
203                                    companyIdString, WebKeys.LIVE_USER_TRACKERS, userTrackersMap);
204                    }
205    
206                    return userTrackersMap;
207            }
208    
209            private void _joinGroup(long companyId, long groupId, long userId) {
210                    Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
211    
212                    Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
213    
214                    if (_getUserTrackers(companyId, userId) != null) {
215                            groupUsers.add(userId);
216                    }
217            }
218    
219            private void _joinGroup(long companyId, long groupId, long[] userIds) {
220                    Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
221    
222                    Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
223    
224                    for (long userId : userIds) {
225                            if (_getUserTrackers(companyId, userId) != null) {
226                                    groupUsers.add(userId);
227                            }
228                    }
229            }
230    
231            private void _leaveGroup(long companyId, long userId, long groupId) {
232                    Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
233    
234                    Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
235    
236                    groupUsers.remove(userId);
237            }
238    
239            private void _leaveGroup(long companyId, long groupId, long[] userIds) {
240                    Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
241    
242                    Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
243    
244                    for (long userId : userIds) {
245                            groupUsers.remove(userId);
246                    }
247            }
248    
249            private void _removeUserTracker(
250                    long companyId, long userId, UserTracker userTracker) {
251    
252                    List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
253    
254                    if (userTrackers != null) {
255                            String sessionId = userTracker.getSessionId();
256    
257                            Iterator<UserTracker> itr = userTrackers.iterator();
258    
259                            while (itr.hasNext()) {
260                                    UserTracker curUserTracker = itr.next();
261    
262                                    if (sessionId.equals(curUserTracker.getSessionId())) {
263                                            itr.remove();
264                                    }
265                            }
266    
267                            if (userTrackers.size() == 0) {
268                                    Map<Long, List<UserTracker>> userTrackersMap =
269                                            _getUserTrackersMap(companyId);
270    
271                                    userTrackersMap.remove(userId);
272                            }
273                    }
274            }
275    
276            private void _signIn(
277                            long companyId, long userId, String sessionId, String remoteAddr,
278                            String remoteHost, String userAgent)
279                    throws SystemException {
280    
281                    _updateGroupStatus(companyId, userId, true);
282    
283                    Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
284    
285                    UserTracker userTracker = sessionUsers.get(sessionId);
286    
287                    if ((userTracker == null) &&
288                            (PropsValues.SESSION_TRACKER_MEMORY_ENABLED)) {
289    
290                            userTracker = UserTrackerUtil.create(0);
291    
292                            userTracker.setCompanyId(companyId);
293                            userTracker.setUserId(userId);
294                            userTracker.setModifiedDate(new Date());
295                            userTracker.setSessionId(sessionId);
296                            userTracker.setRemoteAddr(remoteAddr);
297                            userTracker.setRemoteHost(remoteHost);
298                            userTracker.setUserAgent(userAgent);
299    
300                            sessionUsers.put(sessionId, userTracker);
301    
302                            _addUserTracker(companyId, userId, userTracker);
303                    }
304            }
305    
306            private void _signOut(long companyId, long userId, String sessionId)
307                    throws SystemException {
308    
309                    List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
310    
311                    if ((userTrackers == null) || (userTrackers.size() <= 1)) {
312                            _updateGroupStatus(companyId, userId, false);
313                    }
314    
315                    Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
316    
317                    UserTracker userTracker = sessionUsers.remove(sessionId);
318    
319                    if (userTracker != null) {
320                            try {
321                                    UserTrackerLocalServiceUtil.addUserTracker(
322                                            userTracker.getCompanyId(), userTracker.getUserId(),
323                                            userTracker.getModifiedDate(), sessionId,
324                                            userTracker.getRemoteAddr(), userTracker.getRemoteHost(),
325                                            userTracker.getUserAgent(), userTracker.getPaths());
326                            }
327                            catch (Exception e) {
328                                    if (_log.isWarnEnabled()) {
329                                            _log.warn(e.getMessage());
330                                    }
331                            }
332    
333                            _removeUserTracker(companyId, userId, userTracker);
334                    }
335            }
336    
337            private Map<Long, Set<Long>> _updateGroupStatus(
338                            long companyId, long userId, boolean signedIn)
339                    throws SystemException {
340    
341                    Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
342    
343                    LinkedHashMap<String, Object> groupParams =
344                            new LinkedHashMap<String, Object>();
345    
346                    groupParams.put("usersGroups", userId);
347    
348                    List<Group> communities = GroupLocalServiceUtil.search(
349                            companyId, null, null, groupParams, QueryUtil.ALL_POS,
350                            QueryUtil.ALL_POS);
351    
352                    for (Group community : communities) {
353                            Set<Long> groupUsers = _getGroupUsers(
354                                    liveUsers, community.getGroupId());
355    
356                            if (signedIn) {
357                                    groupUsers.add(userId);
358                            }
359                            else {
360                                    groupUsers.remove(userId);
361                            }
362                    }
363    
364                    return liveUsers;
365            }
366    
367            private static Log _log = LogFactoryUtil.getLog(LiveUsers.class);
368    
369            private static LiveUsers _instance = new LiveUsers();
370    
371    }