1   /**
2    * Copyright (c) 2000-2009 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.log.Log;
28  import com.liferay.portal.kernel.log.LogFactoryUtil;
29  import com.liferay.portal.kernel.util.ConcurrentHashSet;
30  import com.liferay.portal.model.Group;
31  import com.liferay.portal.model.UserTracker;
32  import com.liferay.portal.service.GroupLocalServiceUtil;
33  import com.liferay.portal.service.UserTrackerLocalServiceUtil;
34  import com.liferay.portal.service.persistence.UserTrackerUtil;
35  import com.liferay.portal.util.PropsValues;
36  import com.liferay.portal.util.WebAppPool;
37  import com.liferay.portal.util.WebKeys;
38  
39  import java.util.ArrayList;
40  import java.util.Date;
41  import java.util.Iterator;
42  import java.util.LinkedHashMap;
43  import java.util.List;
44  import java.util.Map;
45  import java.util.Set;
46  import java.util.concurrent.ConcurrentHashMap;
47  
48  /**
49   * <a href="LiveUsers.java.html"><b><i>View Source</i></b></a>
50   *
51   * @author Charles May
52   * @author Brian Wing Shun Chan
53   *
54   */
55  public class LiveUsers {
56  
57      public static void deleteGroup(long companyId, long groupId) {
58          _instance._deleteGroup(companyId, groupId);
59      }
60  
61      public static Set<Long> getGroupUsers(long companyId, long groupId) {
62          return _instance._getGroupUsers(
63              _instance._getLiveUsers(companyId), groupId);
64      }
65  
66      public static int getGroupUsersCount(long companyId, long groupId) {
67          return getGroupUsers(companyId, groupId).size();
68      }
69  
70      public static Map<String, UserTracker> getSessionUsers(long companyId) {
71          return _instance._getSessionUsers(companyId);
72      }
73  
74      public static int getSessionUsersCount(long companyId) {
75          return getSessionUsers(companyId).size();
76      }
77  
78      public static UserTracker getUserTracker(long companyId, String sessionId) {
79          return _instance._getUserTracker(companyId, sessionId);
80      }
81  
82      public static void joinGroup(long companyId, long groupId, long userId) {
83          _instance._joinGroup(companyId, groupId, userId);
84      }
85  
86      public static void joinGroup(long companyId, long groupId, long[] userIds) {
87          _instance._joinGroup(companyId, groupId, userIds);
88      }
89  
90      public static void leaveGroup(long companyId, long groupId, long userId) {
91          _instance._leaveGroup(companyId, groupId, userId);
92      }
93  
94      public static void leaveGroup(
95          long companyId, long groupId, long[] userIds) {
96  
97          _instance._leaveGroup(companyId, groupId, userIds);
98      }
99  
100     public static void signIn(
101             long companyId, long userId, String sessionId, String remoteAddr,
102             String remoteHost, String userAgent)
103         throws SystemException {
104 
105         _instance._signIn(
106             companyId, userId, sessionId, remoteAddr, remoteHost, userAgent);
107     }
108 
109     public static void signOut(long companyId, long userId, String sessionId)
110         throws SystemException {
111 
112         _instance._signOut(companyId, userId, sessionId);
113     }
114 
115     private LiveUsers() {
116     }
117 
118     private void _addUserTracker(
119         long companyId, long userId, UserTracker userTracker) {
120 
121         List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
122 
123         if (userTrackers != null) {
124             userTrackers.add(userTracker);
125         }
126         else {
127             userTrackers = new ArrayList<UserTracker>();
128 
129             userTrackers.add(userTracker);
130 
131             Map<Long, List<UserTracker>> userTrackersMap =
132                 _getUserTrackersMap(companyId);
133 
134             userTrackersMap.put(userId, userTrackers);
135         }
136     }
137 
138     private void _deleteGroup(long companyId, long groupId) {
139         Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
140 
141         liveUsers.remove(groupId);
142     }
143 
144     private Set<Long> _getGroupUsers(
145         Map<Long, Set<Long>> liveUsers, long groupId) {
146 
147         Set<Long> groupUsers = liveUsers.get(groupId);
148 
149         if (groupUsers == null) {
150             groupUsers = new ConcurrentHashSet<Long>();
151 
152             liveUsers.put(groupId, groupUsers);
153         }
154 
155         return groupUsers;
156     }
157 
158     private Map<Long, Set<Long>> _getLiveUsers(long companyId) {
159         String companyIdString = String.valueOf(companyId);
160 
161         Map<Long, Set<Long>> liveUsers = (Map<Long, Set<Long>>)WebAppPool.get(
162             companyIdString, WebKeys.LIVE_USERS);
163 
164         if (liveUsers == null) {
165             liveUsers = new ConcurrentHashMap<Long, Set<Long>>();
166 
167             WebAppPool.put(companyIdString, WebKeys.LIVE_USERS, liveUsers);
168         }
169 
170         return liveUsers;
171     }
172 
173     private Map<String, UserTracker> _getSessionUsers(long companyId) {
174         String companyIdString = String.valueOf(companyId);
175 
176         Map<String, UserTracker> sessionUsers =
177             (Map<String, UserTracker>)WebAppPool.get(
178                 companyIdString, WebKeys.LIVE_SESSION_USERS);
179 
180         if (sessionUsers == null) {
181             sessionUsers = new ConcurrentHashMap<String, UserTracker>();
182 
183             WebAppPool.put(
184                 companyIdString, WebKeys.LIVE_SESSION_USERS, sessionUsers);
185         }
186 
187         return sessionUsers;
188     }
189 
190     private UserTracker _getUserTracker(long companyId, String sessionId) {
191         Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
192 
193         return sessionUsers.get(sessionId);
194     }
195 
196     private List<UserTracker> _getUserTrackers(long companyId, long userId) {
197         Map<Long, List<UserTracker>> userTrackersMap = _getUserTrackersMap(
198             companyId);
199 
200         return userTrackersMap.get(userId);
201     }
202 
203     private Map<Long, List<UserTracker>> _getUserTrackersMap(long companyId) {
204         String companyIdString = String.valueOf(companyId);
205 
206         Map<Long, List<UserTracker>> userTrackersMap =
207             (Map<Long, List<UserTracker>>)WebAppPool.get(
208                 companyIdString, WebKeys.LIVE_USER_TRACKERS);
209 
210         if (userTrackersMap == null) {
211             userTrackersMap = new ConcurrentHashMap<Long, List<UserTracker>>();
212 
213             WebAppPool.put(
214                 companyIdString, WebKeys.LIVE_USER_TRACKERS, userTrackersMap);
215         }
216 
217         return userTrackersMap;
218     }
219 
220     private void _joinGroup(long companyId, long groupId, long userId) {
221         Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
222 
223         Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
224 
225         if (_getUserTrackers(companyId, userId) != null) {
226             groupUsers.add(userId);
227         }
228     }
229 
230     private void _joinGroup(long companyId, long groupId, long[] userIds) {
231         Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
232 
233         Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
234 
235         for (long userId : userIds) {
236             if (_getUserTrackers(companyId, userId) != null) {
237                 groupUsers.add(userId);
238             }
239         }
240     }
241 
242     private void _leaveGroup(long companyId, long userId, long groupId) {
243         Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
244 
245         Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
246 
247         groupUsers.remove(userId);
248     }
249 
250     private void _leaveGroup(long companyId, long groupId, long[] userIds) {
251         Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
252 
253         Set<Long> groupUsers = _getGroupUsers(liveUsers, groupId);
254 
255         for (long userId : userIds) {
256             groupUsers.remove(userId);
257         }
258     }
259 
260     private void _removeUserTracker(
261         long companyId, long userId, UserTracker userTracker) {
262 
263         List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
264 
265         if (userTrackers != null) {
266             String sessionId = userTracker.getSessionId();
267 
268             Iterator<UserTracker> itr = userTrackers.iterator();
269 
270             while (itr.hasNext()) {
271                 UserTracker curUserTracker = itr.next();
272 
273                 if (sessionId.equals(curUserTracker.getSessionId())) {
274                     itr.remove();
275                 }
276             }
277 
278             if (userTrackers.size() == 0) {
279                 Map<Long, List<UserTracker>> userTrackersMap =
280                     _getUserTrackersMap(companyId);
281 
282                 userTrackersMap.remove(userId);
283             }
284         }
285     }
286 
287     private void _signIn(
288             long companyId, long userId, String sessionId, String remoteAddr,
289             String remoteHost, String userAgent)
290         throws SystemException {
291 
292         _updateGroupStatus(companyId, userId, true);
293 
294         Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
295 
296         UserTracker userTracker = sessionUsers.get(sessionId);
297 
298         if ((userTracker == null) &&
299             (PropsValues.SESSION_TRACKER_MEMORY_ENABLED)) {
300 
301             userTracker = UserTrackerUtil.create(0);
302 
303             userTracker.setCompanyId(companyId);
304             userTracker.setUserId(userId);
305             userTracker.setModifiedDate(new Date());
306             userTracker.setSessionId(sessionId);
307             userTracker.setRemoteAddr(remoteAddr);
308             userTracker.setRemoteHost(remoteHost);
309             userTracker.setUserAgent(userAgent);
310 
311             sessionUsers.put(sessionId, userTracker);
312 
313             _addUserTracker(companyId, userId, userTracker);
314         }
315     }
316 
317     private void _signOut(long companyId, long userId, String sessionId)
318         throws SystemException {
319 
320         List<UserTracker> userTrackers = _getUserTrackers(companyId, userId);
321 
322         if ((userTrackers == null) || (userTrackers.size() <= 1)) {
323             _updateGroupStatus(companyId, userId, false);
324         }
325 
326         Map<String, UserTracker> sessionUsers = _getSessionUsers(companyId);
327 
328         UserTracker userTracker = sessionUsers.remove(sessionId);
329 
330         if (userTracker != null) {
331             try {
332                 UserTrackerLocalServiceUtil.addUserTracker(
333                     userTracker.getCompanyId(), userTracker.getUserId(),
334                     userTracker.getModifiedDate(), sessionId,
335                     userTracker.getRemoteAddr(), userTracker.getRemoteHost(),
336                     userTracker.getUserAgent(), userTracker.getPaths());
337             }
338             catch (Exception e) {
339                 if (_log.isWarnEnabled()) {
340                     _log.warn(e.getMessage());
341                 }
342             }
343 
344             _removeUserTracker(companyId, userId, userTracker);
345         }
346     }
347 
348     private Map<Long, Set<Long>> _updateGroupStatus(
349             long companyId, long userId, boolean signedIn)
350         throws SystemException {
351 
352         Map<Long, Set<Long>> liveUsers = _getLiveUsers(companyId);
353 
354         LinkedHashMap<String, Object> groupParams =
355             new LinkedHashMap<String, Object>();
356 
357         groupParams.put("usersGroups", userId);
358 
359         List<Group> communities = GroupLocalServiceUtil.search(
360             companyId, null, null, groupParams, QueryUtil.ALL_POS,
361             QueryUtil.ALL_POS);
362 
363         for (Group community : communities) {
364             Set<Long> groupUsers = _getGroupUsers(
365                 liveUsers, community.getGroupId());
366 
367             if (signedIn) {
368                 groupUsers.add(userId);
369             }
370             else {
371                 groupUsers.remove(userId);
372             }
373         }
374 
375         return liveUsers;
376     }
377 
378     private static Log _log = LogFactoryUtil.getLog(LiveUsers.class);
379 
380     private static LiveUsers _instance = new LiveUsers();
381 
382 }