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