001/* 002 * GWTEventService 003 * Copyright (c) 2011 and beyond, strawbill UG (haftungsbeschr?nkt) 004 * 005 * This is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Lesser General Public License as 007 * published by the Free Software Foundation; either version 3 of 008 * the License, or (at your option) any later version. 009 * Other licensing for GWTEventService may also be possible on request. 010 * Please view the license.txt of the project for more information. 011 * 012 * This software is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this software; if not, write to the Free 019 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 020 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 021 */ 022package de.novanic.eventservice.service.registry.user; 023 024import de.novanic.eventservice.service.UserTimeoutListener; 025import de.novanic.eventservice.util.PlatformUtil; 026 027import java.util.*; 028import java.util.concurrent.ConcurrentLinkedQueue; 029 030/** 031 * UserActivityScheduler observes the activities of the users/clients and can report timeouts. 032 * To observe the users/clients, the UserActivityScheduler must be started with the start method 033 * ({@link UserActivityScheduler#start(boolean)}). 034 * 035 * @author sstrohschein 036 * <br>Date: 20.01.2009 037 * <br>Time: 23:30:47 038 */ 039public class UserActivityScheduler 040{ 041 private final Collection<UserInfo> myUserInfoCollection; 042 private final Queue<UserTimeoutListener> myTimeoutListeners; 043 private final long myTimeoutInterval; 044 private Timer myTimer; 045 private TimeoutTimerTask myTimeoutTimerTask; 046 private boolean myIsAutoClean; 047 private boolean isActive; 048 049 /** 050 * Creates a new UserActivityScheduler with a reference to a Collection of {@link UserInfo}. 051 * @param aUserInfoCollection all UserInfo instances to observe 052 * @param aTimeoutInterval milliseconds to the timeout 053 */ 054 protected UserActivityScheduler(Collection<UserInfo> aUserInfoCollection, long aTimeoutInterval) { 055 myUserInfoCollection = aUserInfoCollection; 056 myTimeoutInterval = aTimeoutInterval; 057 myTimeoutListeners = new ConcurrentLinkedQueue<UserTimeoutListener>(); 058 } 059 060 /** 061 * Adds a {@link de.novanic.eventservice.service.UserTimeoutListener} to the {@link de.novanic.eventservice.service.registry.user.UserActivityScheduler}. 062 * @param aTimeoutListener listener to get reported timeouts 063 */ 064 public void addTimeoutListener(UserTimeoutListener aTimeoutListener) { 065 myTimeoutListeners.add(aTimeoutListener); 066 } 067 068 /** 069 * Removes a {@link de.novanic.eventservice.service.UserTimeoutListener} from the {@link de.novanic.eventservice.service.registry.user.UserActivityScheduler}. 070 * @param aTimeoutListener listener to get reported timeouts 071 */ 072 public void removeTimeoutListener(UserTimeoutListener aTimeoutListener) { 073 myTimeoutListeners.remove(aTimeoutListener); 074 } 075 076 /** 077 * Removes all {@link de.novanic.eventservice.service.UserTimeoutListener} from the {@link de.novanic.eventservice.service.registry.user.UserActivityScheduler}. 078 */ 079 public void removeTimeoutListeners() { 080 myTimeoutListeners.clear(); 081 } 082 083 /** 084 * That method starts the UserActivityScheduler to observe the users/clients. The activities will be checked like 085 * the timeout interval is configured ({@link de.novanic.eventservice.config.EventServiceConfiguration#getTimeoutTime()}). 086 * @param isAutoClean when set to true, the users/clients are removed automatically on timeout 087 */ 088 public void start(boolean isAutoClean) { 089 if(!isActive) { 090 myIsAutoClean = isAutoClean; 091 myTimer = new Timer("GWTEventService-UserActivityScheduler", true); 092 myTimeoutTimerTask = new TimeoutTimerTask(); 093 isActive = true; 094 schedule(myTimer, myTimeoutTimerTask, myTimeoutInterval); 095 } 096 } 097 098 /** 099 * Stops the UserActivityScheduler. At that point, the users/clients won't be observed anymore. 100 */ 101 public void stop() { 102 if(isActive) { 103 isActive = false; 104 105 if(myTimer != null) { 106 myTimer.cancel(); 107 } 108 if(myTimeoutTimerTask != null) { 109 myTimeoutTimerTask.cancel(); 110 } 111 if(myTimer != null) { 112 myTimer.purge(); 113 } 114 } 115 } 116 117 /** 118 * Returns the state of the UserActivityScheduler. Returns true when the UserActivityScheduler is started 119 * ({@link UserActivityScheduler#start(boolean)}) and false when the UserActivityScheduler isn't started or stopped 120 * ({@link de.novanic.eventservice.service.registry.user.UserActivityScheduler#stop()}). 121 * @return true when running/started, false when running (not started or stopped) 122 */ 123 public boolean isActive() { 124 return isActive; 125 } 126 127 /** 128 * Returns the configured timeout time/interval. The user activity is checked in that interval. 129 * @return timeout time/interval 130 */ 131 public long getTimeoutInterval() { 132 return myTimeoutInterval; 133 } 134 135 /** 136 * That method must be called to report a user activity and protects the user from a timeout for the time of the 137 * timeout interval ({@link de.novanic.eventservice.config.EventServiceConfiguration#getTimeoutTime()}). 138 * @param aUserInfo user/client to refresh 139 */ 140 public void reportUserActivity(UserInfo aUserInfo) { 141 aUserInfo.reportUserActivity(); 142 } 143 144 /** 145 * That method is used to measure the timeout and it will remove the user automatically, if configured with the start method 146 * ({@link de.novanic.eventservice.service.registry.user.UserActivityScheduler#start(boolean)}). 147 * @param aTimer timer to schedule 148 * @param aTimeoutTimerTask TimeoutTimerTask 149 * @param aTimeoutInterval interval to check for timeouts 150 */ 151 private void schedule(Timer aTimer, TimeoutTimerTask aTimeoutTimerTask, long aTimeoutInterval) { 152 aTimer.schedule(aTimeoutTimerTask, 0L, aTimeoutInterval); 153 } 154 155 /** 156 * The TimeoutTimerTask runs in the interval which is configured with {@link de.novanic.eventservice.config.EventServiceConfiguration#getTimeoutTime()}. 157 * All added {@link de.novanic.eventservice.service.UserTimeoutListener} get informed about the occurred timeout 158 * with the execution of that {@link java.util.TimerTask}. The TimeoutTimerTask starts when the UserActivityScheduler 159 * is started ({@link de.novanic.eventservice.service.registry.user.UserActivityScheduler#start(boolean)}) and stops when 160 * the UserActivityScheduler is stopped ({@link de.novanic.eventservice.service.registry.user.UserActivityScheduler#stop()}). 161 */ 162 private class TimeoutTimerTask extends TimerTask 163 { 164 public void run() { 165 final long theTimeoutCriteriaTime = PlatformUtil.getCurrentTime() - myTimeoutInterval; 166 167 Iterator<UserInfo> theUserInfoIterator = myUserInfoCollection.iterator(); 168 while(theUserInfoIterator.hasNext()) { 169 UserInfo theUserInfo = theUserInfoIterator.next(); 170 if(isTimeout(theUserInfo, theTimeoutCriteriaTime)) { 171 //report about user timeout 172 for(UserTimeoutListener theTimeoutListener: myTimeoutListeners) { 173 theTimeoutListener.onTimeout(theUserInfo); 174 } 175 //remove the user/client automatically if auto-clean is switched on 176 if(myIsAutoClean) { 177 theUserInfoIterator.remove(); 178 } 179 } 180 } 181 } 182 183 /** 184 * Reports a timeout when {@link UserInfo#getLastActivityTime()} is greater than the max. timeout time (the 185 * current time + {@link de.novanic.eventservice.config.EventServiceConfiguration#getTimeoutTime()}). 186 * @param aUserInfo user/client to check for a timeout 187 * @param aTimeoutCriteriaTime timeout time to compare {@link UserInfo#getLastActivityTime()} 188 * @return True if the {@link UserInfo#getLastActivityTime()} is too long ago, otherwise true 189 */ 190 private boolean isTimeout(UserInfo aUserInfo, long aTimeoutCriteriaTime) { 191 return (aUserInfo.getLastActivityTime() <= aTimeoutCriteriaTime); 192 } 193 } 194}