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