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