package javax.management.timer;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.NotificationBroadcasterSupport;
import javax.management.ObjectName;
import org.jboss.mx.util.RunnableScheduler;
import org.jboss.mx.util.SchedulableRunnable;
import org.jboss.logging.Logger;
public class Timer
extends NotificationBroadcasterSupport
implements TimerMBean, MBeanRegistration
{
private static Logger log = Logger.getLogger(Timer.class);
public static final long ONE_SECOND = 1000;
public static final long ONE_MINUTE = ONE_SECOND * 60;
public static final long ONE_HOUR = ONE_MINUTE * 60;
public static final long ONE_DAY = ONE_HOUR * 24;
public static final long ONE_WEEK = ONE_DAY * 7;
private static final int SEND_NO = 0;
private static final int SEND_START = 1;
private static final int SEND_NORMAL = 2;
int nextId = 0;
long sequenceNumber = 0;
boolean sendPastNotifications = false;
boolean active = false;
ObjectName objectName;
HashMap notifications = new HashMap();
private RunnableScheduler scheduler = new RunnableScheduler();
public Integer addNotification(String type, String message, Object userData,
Date date)
throws IllegalArgumentException
{
return addNotification(type, message, userData, date, 0);
}
public Integer addNotification(String type, String message, Object userData,
Date date, long period)
throws IllegalArgumentException
{
return addNotification(type, message, userData, date, period, 0);
}
public Integer addNotification(String type, String message,
Object userData, Date date, long period, long occurences)
throws IllegalArgumentException
{
int newId = 0;
newId = ++nextId;
Integer id = new Integer(newId);
RegisteredNotification rn =
new RegisteredNotification(id, type, message, userData, date, period,
occurences);
synchronized(notifications)
{
notifications.put(id, rn);
rn.setNextRun(rn.nextDate);
rn.setScheduler(scheduler);
}
return id;
}
public Vector getAllNotificationIDs()
{
synchronized(notifications)
{
return new Vector(notifications.keySet());
}
}
public Date getDate(Integer id)
{
RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
if (rn == null)
return null;
return new Date(rn.startDate);
}
public int getNbNotifications()
{
return notifications.size();
}
public Long getNbOccurences(Integer id)
{
RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
if (rn == null)
return null;
return new Long(rn.occurences);
}
public Boolean getFixedRate(Integer id)
{
throw new RuntimeException("NYI");
}
public Vector getNotificationIDs(String type)
{
Vector result = new Vector();
synchronized (notifications)
{
Iterator iterator = notifications.values().iterator();
while (iterator.hasNext())
{
RegisteredNotification rn = (RegisteredNotification) iterator.next();
if (rn.type.equals(type))
result.add(rn.id);
}
}
return result;
}
public String getNotificationMessage(Integer id)
{
RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
if (rn == null)
return null;
return rn.message;
}
public String getNotificationType(Integer id)
{
RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
if (rn == null)
return null;
return rn.type;
}
public Object getNotificationUserData(Integer id)
{
RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
if (rn == null)
return null;
return rn.userData;
}
public Long getPeriod(Integer id)
{
RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
if (rn == null)
return null;
return new Long(rn.period);
}
public boolean getSendPastNotifications()
{
return sendPastNotifications;
}
public boolean isActive()
{
return active;
}
public boolean isEmpty()
{
return notifications.isEmpty();
}
public void removeAllNotifications()
{
synchronized(notifications)
{
Iterator iterator = notifications.values().iterator();
while (iterator.hasNext())
{
RegisteredNotification rn = (RegisteredNotification) iterator.next();
rn.setScheduler(null);
iterator.remove();
}
}
synchronized (this)
{
nextId = 0;
}
}
public void removeNotification(Integer id)
throws InstanceNotFoundException
{
log.debug("removeNotification: " + objectName + ",id=" + id);
synchronized(notifications)
{
RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
if (rn == null)
throw new InstanceNotFoundException("No notification id : " +
id.toString());
rn.setScheduler(null);
notifications.remove(id);
}
}
public void removeNotifications(String type)
throws InstanceNotFoundException
{
boolean found = false;
log.debug("removeNotifications: " + objectName + ",type=" + type);
synchronized(notifications)
{
Iterator iterator = notifications.values().iterator();
while (iterator.hasNext())
{
RegisteredNotification rn = (RegisteredNotification) iterator.next();
if (rn.type.equals(type))
{
rn.setScheduler(null);
iterator.remove();
found = true;
}
}
}
if (found == false)
throw new InstanceNotFoundException("Nothing registered for type: " +
type);
}
public void setSendPastNotifications(boolean value)
{
log.debug("setSendPastNotifications: " + objectName + ",value=" + value);
sendPastNotifications = value;
}
public synchronized void start()
{
if (active == true)
return;
active = true;
log.debug("start: " + objectName + " at " + new Date());
synchronized (notifications)
{
Iterator iterator = notifications.values().iterator();
while (iterator.hasNext())
{
RegisteredNotification rn = (RegisteredNotification) iterator.next();
if (sendPastNotifications)
rn.sendType = SEND_START;
else
rn.sendType = SEND_NO;
sendNotifications(rn);
rn.sendType = SEND_NORMAL;
}
}
scheduler.start();
}
public synchronized void stop()
{
if (active == false)
return;
log.debug("stop: " + objectName + ",now=" + new Date());
active = false;
scheduler.stop();
}
public Integer addNotification(String type, String message, Object userData, Date date, long period, long nbOccurences, boolean fixedRate) throws IllegalArgumentException
{
throw new RuntimeException("NYI");
}
public ObjectName preRegister(MBeanServer server, ObjectName objectName)
throws Exception
{
this.objectName = objectName;
return objectName;
}
public void postRegister(Boolean registrationDone)
{
}
public void preDeregister()
throws Exception
{
stop();
}
public void postDeregister()
{
}
private void sendNotifications(RegisteredNotification rn)
{
while (isActive() && rn.nextDate != 0
&& rn.nextDate <= System.currentTimeMillis())
{
if (rn.sendType != SEND_NO)
{
long seq = 0;
synchronized (this)
{
seq = ++sequenceNumber;
}
log.debug("sendNotification: " + rn);
TimerNotification tn = new TimerNotification(rn.type, objectName,
seq, rn.nextDate, rn.message, rn.id);
tn.setUserData(rn.userData);
sendNotification(tn);
}
do
{
if (rn.calcNextDate() == false)
{
synchronized (notifications)
{
log.debug("remove: " + rn);
notifications.remove(rn.id);
}
}
}
while (isActive() && rn.sendType != SEND_START && rn.nextDate != 0
&& rn.occurences == 0 && rn.nextDate < System.currentTimeMillis());
}
if (rn.nextDate != 0)
rn.setNextRun(rn.nextDate);
}
private class RegisteredNotification
extends SchedulableRunnable
{
public Integer id;
public String type;
public String message;
public Object userData;
public long startDate;
public long period;
public long occurences;
public int sendType = SEND_NORMAL;
public long nextDate = 0;
public RegisteredNotification(Integer id, String type, String message, Object userData, Date startDate, long period, long occurences)
throws IllegalArgumentException
{
if (startDate == null)
throw new IllegalArgumentException("Null Date");
if (period < 0)
throw new IllegalArgumentException("Negative Period");
if (occurences < 0)
throw new IllegalArgumentException("Negative Occurences");
this.startDate = startDate.getTime();
if (startDate.getTime() < System.currentTimeMillis())
{
log.warn("startDate [" + startDate + "] in the past, set to now");
this.startDate = System.currentTimeMillis();
}
this.id = id;
this.type = type;
this.message = message;
this.userData = userData;
this.period = period;
this.occurences = occurences;
this.nextDate = this.startDate;
String msgStr = "new " + this.toString();
log.debug(msgStr);
}
boolean calcNextDate()
{
if (period == 0)
{
nextDate = 0;
return false;
}
if (occurences != 0 && --occurences == 0)
{
nextDate = 0;
return false;
}
nextDate += period;
return true;
}
public void doRun()
{
sendNotifications(this);
}
public String toString()
{
return " RegisteredNotification: [timer=" + objectName + ",id=" + id + ",startDate=" + new Date(startDate) +
",periode=" + period + ",occurences=" + occurences + ",nextDate=" + new Date(nextDate) + "]";
}
}
}