1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.liveusers;
24  
25  import com.liferay.portal.SystemException;
26  import com.liferay.portal.kernel.dao.orm.QueryUtil;
27  import com.liferay.portal.kernel.util.ConcurrentHashSet;
28  import com.liferay.portal.model.Group;
29  import com.liferay.portal.model.UserTracker;
30  import com.liferay.portal.service.GroupLocalServiceUtil;
31  import com.liferay.portal.service.UserTrackerLocalServiceUtil;
32  import com.liferay.portal.service.persistence.UserTrackerUtil;
33  import com.liferay.portal.util.PropsValues;
34  import com.liferay.portal.util.WebAppPool;
35  import com.liferay.portal.util.WebKeys;
36  
37  import java.util.ArrayList;
38  import java.util.Date;
39  import java.util.Iterator;
40  import java.util.LinkedHashMap;
41  import java.util.List;
42  import java.util.Map;
43  import java.util.Set;
44  import java.util.concurrent.ConcurrentHashMap;
45  
46  import org.apache.commons.logging.Log;
47  import org.apache.commons.logging.LogFactory;
48  
49  /**
50   * <a href="LiveUsers.java.html"><b><i>View Source</i></b></a>
51   *
52   * @author Charles May
53   * @author Brian Wing Shun Chan
54   *
55   */
56  public class LiveUsers {
57  
58      public static void deleteGroup(long companyId, long groupId) {
59          _instance._deleteGroup(companyId, groupId);
60      }
61  
62      public static Set<Long> getGroupUsers(long companyId, long groupId) {
63          return _instance._getGroupUsers(
64              _instance._getLiveUsers(companyId), groupId);
65      }
66  
67      public static int getGroupUsersCount(long companyId, long groupId) {
68          return getGroupUsers(companyId, groupId).size();
69      }
70  
71      public static Map<String, UserTracker> getSessionUsers(long companyId) {
72          return _instance._getSessionUsers(companyId);
73      }
74  
75      public static int getSessionUsersCount(long companyId) {
76          return getSessionUsers(companyId).size();
77      }
78  
79      public static UserTracker getUserTracker(long companyId, String sessionId) {
80          return _instance._getUserTracker(companyId, sessionId);
81      }
82  
83      public static void joinGroup(long companyId, long groupId, long userId) {
84          _instance._joinGroup(companyId, groupId, userId);
85      }
86  
87      public static void joinGroup(long companyId, long groupId, long[] userIds) {
88          _instance._joinGroup(companyId, groupId, userIds);
89      }
90  
91      public static void leaveGroup(long companyId, long groupId, long userId) {
92          _instance._leaveGroup(companyId, groupId, userId);
93      }
94  
95      public static void leaveGroup(
96          long companyId, long groupId, long[] userIds) {
97  
98          _instance._leaveGroup(companyId, groupId, userIds);
99      }
100 
101     public static void signIn(
102             long companyId, long userId, String sessionId, String remoteAddr,
103             String remoteHost, String userAgent)
104         throws SystemException {
105 
106         _instance._signIn(
107             companyId, userId, sessionId, remoteAddr, remoteHost, userAgent);
108     }
109 
110     public static void signOut(long companyId, long userId, String sessionId)
111         throws SystemException {
112 
113         _instance._signOut(companyId, userId, sessionId);
114     }
115 
116     private LiveUsers() {
117     }
118 
119     private void _addUserTracker(
120         long companyId, long userId, UserTracker userTracker) {
121 
122         List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
123 
124         if (userTrackers != null) {
125             userTrackers.add(userTracker);
126         }
127         else {
128             userTrackers = new ArrayList<UserTracker>();
129 
130             userTrackers.add(userTracker);
131 
132             Map<Long, List<UserTracker>> userTrackersMap =
133                 _getUserTrackersMap(companyId);
134 
135             userTrackersMap.put(userId, userTrackers);
136         }
137     }
138 
139     private void _deleteGroup(long companyId, long groupId) {
140         Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
141 
142         liveUsers.remove(groupId);
143     }
144 
145     private Set<Long> _getGroupUsers(
146         Map<Long, Set<Long>> liveUsers, long groupId) {
147 
148         Set<Long> groupUsers = liveUsers.get(groupId);
149 
150         if (groupUsers == null) {
151             groupUsers = new ConcurrentHashSet<Long>();
152 
153             liveUsers.put(groupId, groupUsers);
154         }
155 
156         return groupUsers;
157     }
158 
159     private Map<Long, Set<Long>> _getLiveUsers(long companyId) {
160         String companyIdString = String.valueOf(companyId);
161 
162         Map<Long, Set<Long>> liveUsers = (Map<Long, Set<Long>>)WebAppPool.get(
163             companyIdString, WebKeys.LIVE_USERS);
164 
165         if (liveUsers == null) {
166             liveUsers = new ConcurrentHashMap<Long, Set<Long>>();
167 
168             WebAppPool.put(companyIdString, WebKeys.LIVE_USERS, liveUsers);
169         }
170 
171         return liveUsers;
172     }
173 
174     private Map<String, UserTracker> _getSessionUsers(long companyId) {
175         String companyIdString = String.valueOf(companyId);
176 
177         Map<String, UserTracker> sessionUsers =
178             (Map<String, UserTracker>)WebAppPool.get(
179                 companyIdString, WebKeys.LIVE_SESSION_USERS);
180 
181         if (sessionUsers == null) {
182             sessionUsers = new ConcurrentHashMap<String, UserTracker>();
183 
184             WebAppPool.put(
185                 companyIdString, WebKeys.LIVE_SESSION_USERS, sessionUsers);
186         }
187 
188         return sessionUsers;
189     }
190 
191     private UserTracker _getUserTracker(long companyId, String sessionId) {
192         Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
193 
194         return sessionUsers.get(sessionId);
195     }
196 
197     private List<UserTracker> _getUserTrackers(long companyId, long userId) {
198         Map<Long, List<UserTracker>> userTrackersMap = _getUserTrackersMap(
199             companyId);
200 
201         return userTrackersMap.get(userId);
202     }
203 
204     private Map<Long, List<UserTracker>> _getUserTrackersMap(long companyId) {
205         String companyIdString = String.valueOf(companyId);
206 
207         Map<Long, List<UserTracker>> userTrackersMap =
208             (Map<Long, List<UserTracker>>)WebAppPool.get(
209                 companyIdString, WebKeys.LIVE_USER_TRACKERS);
210 
211         if (userTrackersMap == null) {
212             userTrackersMap = new ConcurrentHashMap<Long, List<UserTracker>>();
213 
214             WebAppPool.put(
215                 companyIdString, WebKeys.LIVE_USER_TRACKERS, userTrackersMap);
216         }
217 
218         return userTrackersMap;
219     }
220 
221     private void _joinGroup(long companyId, long groupId, long userId) {
222         Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
223 
224         Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
225 
226         if (_getUserTrackers(companyId, userId) != null) {
227             groupUsers.add(userId);
228         }
229     }
230 
231     private void _joinGroup(long companyId, long groupId, long[] userIds) {
232         Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
233 
234         Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
235 
236         for (long userId : userIds) {
237             if (_getUserTrackers(companyId, userId) != null) {
238                 groupUsers.add(userId);
239             }
240         }
241     }
242 
243     private void _leaveGroup(long companyId, long userId, long groupId) {
244         Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
245 
246         Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
247 
248         groupUsers.remove(userId);
249     }
250 
251     private void _leaveGroup(long companyId, long groupId, long[] userIds) {
252         Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
253 
254         Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
255 
256         for (long userId : userIds) {
257             groupUsers.remove(userId);
258         }
259     }
260 
261     private void _removeUserTracker(
262         long companyId, long userId, UserTracker userTracker) {
263 
264         List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
265 
266         if (userTrackers != null) {
267             String sessionId = userTracker.getSessionId();
268 
269             Iterator<UserTracker> itr = userTrackers.iterator();
270 
271             while (itr.hasNext()) {
272                 UserTracker curUserTracker = itr.next();
273 
274                 if (sessionId.equals(curUserTracker.getSessionId())) {
275                     itr.remove();
276                 }
277             }
278 
279             if (userTrackers.size() == 0) {
280                 Map<Long, List<UserTracker>> userTrackersMap =
281                     _getUserTrackersMap(companyId);
282 
283                 userTrackersMap.remove(userId);
284             }
285         }
286     }
287 
288     private void _signIn(
289             long companyId, long userId, String sessionId, String remoteAddr,
290             String remoteHost, String userAgent)
291         throws SystemException {
292 
293         _updateGroupStatus(companyId, userId, true);
294 
295         Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
296 
297         UserTracker userTracker = sessionUsers.get(sessionId);
298 
299         if ((userTracker == null) &&
300             (PropsValues.SESSION_TRACKER_MEMORY_ENABLED)) {
301 
302             userTracker = UserTrackerUtil.create(0);
303 
304             userTracker.setCompanyId(companyId);
305             userTracker.setUserId(userId);
306             userTracker.setModifiedDate(new Date());
307             userTracker.setSessionId(sessionId);
308             userTracker.setRemoteAddr(remoteAddr);
309             userTracker.setRemoteHost(remoteHost);
310             userTracker.setUserAgent(userAgent);
311 
312             sessionUsers.put(sessionId, userTracker);
313 
314             _addUserTracker(companyId, userId, userTracker);
315         }
316     }
317 
318     private void _signOut(long companyId, long userId, String sessionId)
319         throws SystemException {
320 
321         List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
322 
323         if ((userTrackers == null) || (userTrackers.size() <= 1)) {
324             _updateGroupStatus(companyId, userId, false);
325         }
326 
327         Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
328 
329         UserTracker userTracker = sessionUsers.remove(sessionId);
330 
331         if (userTracker != null) {
332             try {
333                 UserTrackerLocalServiceUtil.addUserTracker(
334                     userTracker.getCompanyId(), userTracker.getUserId(),
335                     userTracker.getModifiedDate(), sessionId,
336                     userTracker.getRemoteAddr(), userTracker.getRemoteHost(),
337                     userTracker.getUserAgent(), userTracker.getPaths());
338             }
339             catch (Exception e) {
340                 if (_log.isWarnEnabled()) {
341                     _log.warn(e.getMessage());
342                 }
343             }
344 
345             _removeUserTracker(companyId, userId, userTracker);
346         }
347     }
348 
349     private Map<Long, Set<Long>> _updateGroupStatus(
350             long companyId, long userId, boolean signedIn)
351         throws SystemException {
352 
353         Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
354 
355         LinkedHashMap<String, Object> groupParams =
356             new LinkedHashMap<String, Object>();
357 
358         groupParams.put("usersGroups", userId);
359 
360         List<Group> communities = GroupLocalServiceUtil.search(
361             companyId, null, null, groupParams, QueryUtil.ALL_POS,
362             QueryUtil.ALL_POS);
363 
364         for (Group community : communities) {
365             Set<Long> groupUsers = _getGroupUsers(
366                 liveUsers, community.getGroupId());
367 
368             if (signedIn) {
369                 groupUsers.add(userId);
370             }
371             else {
372                 groupUsers.remove(userId);
373             }
374         }
375 
376         return liveUsers;
377     }
378 
379     private static Log _log = LogFactory.getLog(LiveUsers.class);
380 
381     private static LiveUsers _instance = new LiveUsers();
382 
383 }