/* * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.management.timer; import static com.sun.jmx.defaults.JmxProperties.TIMER_LOGGER;import java.util.ArrayList;import java.util.Date;import java.util.Hashtable;import java.util.Iterator;import java.util.Map;import java.util.Set;import java.util.TreeSet;import java.util.Vector;import java.util.logging.Level; // jmx imports//import javax.management.InstanceNotFoundException;import javax.management.MBeanNotificationInfo;import javax.management.MBeanRegistration;import javax.management.MBeanServer;import javax.management.NotificationBroadcasterSupport;import javax.management.ObjectName; /** * * Provides the implementation of the timer MBean. * The timer MBean sends out an alarm at a specified time * that wakes up all the listeners registered to receive timer notifications. * <P> * * This class manages a list of dated timer notifications. * A method allows users to add/remove as many notifications as required. * When a timer notification is emitted by the timer and becomes obsolete, * it is automatically removed from the list of timer notifications. * <BR>Additional timer notifications can be added into regularly repeating notifications. * <P> * * Note: * <OL> * <LI>When sending timer notifications, the timer updates the notification sequence number * irrespective of the notification type. * <LI>The timer service relies on the system date of the host where the <CODE>Timer</CODE> class is loaded. * Listeners may receive untimely notifications * if their host has a different system date. * To avoid such problems, synchronize the system date of all host machines where timing is needed. * <LI>The default behavior for periodic notifications is <i>fixed-delay execution</i>, as * specified in {@link java.util.Timer}. In order to use <i>fixed-rate execution</i>, use the * overloaded {@link #addNotification(String, String, Object, Date, long, long, boolean)} method. * <LI>Notification listeners are potentially all executed in the same * thread. Therefore, they should execute rapidly to avoid holding up * other listeners or perturbing the regularity of fixed-delay * executions. See {@link NotificationBroadcasterSupport}. * </OL> * * @since 1.5 */public class Timer extends NotificationBroadcasterSupport implements TimerMBean, MBeanRegistration { /* * ------------------------------------------ * PUBLIC VARIABLES * ------------------------------------------ */ /** * Number of milliseconds in one second. * Useful constant for the <CODE>addNotification</CODE> method. */ public static final long ONE_SECOND = 1000; /** * Number of milliseconds in one minute. * Useful constant for the <CODE>addNotification</CODE> method. */ public static final long ONE_MINUTE = 60*ONE_SECOND; /** * Number of milliseconds in one hour. * Useful constant for the <CODE>addNotification</CODE> method. */ public static final long ONE_HOUR = 60*ONE_MINUTE; /** * Number of milliseconds in one day. * Useful constant for the <CODE>addNotification</CODE> method. */ public static final long ONE_DAY = 24*ONE_HOUR; /** * Number of milliseconds in one week. * Useful constant for the <CODE>addNotification</CODE> method. */ public static final long ONE_WEEK = 7*ONE_DAY; /* * ------------------------------------------ * PRIVATE VARIABLES * ------------------------------------------ */ /** * Table containing all the timer notifications of this timer, * with the associated date, period and number of occurrences. */ private Map<Integer,Object[]> timerTable = new Hashtable<Integer,Object[]>(); /** * Past notifications sending on/off flag value. * This attribute is used to specify if the timer has to send past notifications after start. * <BR>The default value is set to <CODE>false</CODE>. */ private boolean sendPastNotifications = false; /** * Timer state. * The default value is set to <CODE>false</CODE>. */ private transient boolean isActive = false; /** * Timer sequence number. * The default value is set to 0. */ private transient long sequenceNumber = 0; // Flags needed to keep the indexes of the objects in the array. // private static final int TIMER_NOTIF_INDEX = 0; private static final int TIMER_DATE_INDEX = 1; private static final int TIMER_PERIOD_INDEX = 2; private static final int TIMER_NB_OCCUR_INDEX = 3; private static final int ALARM_CLOCK_INDEX = 4; private static final int FIXED_RATE_INDEX = 5; /** * The notification counter ID. * Used to keep the max key value inserted into the timer table. */ private int counterID = 0; private java.util.Timer timer; /* * ------------------------------------------ * CONSTRUCTORS * ------------------------------------------ */ /** * Default constructor. */ public Timer() { } /* * ------------------------------------------ * PUBLIC METHODS * ------------------------------------------ */ /** * Allows the timer MBean to perform any operations it needs before being registered * in the MBean server. * <P> * Not used in this context. * * @param server The MBean server in which the timer MBean will be registered. * @param name The object name of the timer MBean. * * @return The name of the timer MBean registered. * * @exception java.lang.Exception */ public ObjectName preRegister(MBeanServer server, ObjectName name) throws java.lang.Exception { return name; } /** * Allows the timer MBean to perform any operations needed after having been * registered in the MBean server or after the registration has failed. * <P> * Not used in this context. */ public void postRegister (Boolean registrationDone) { } /** * Allows the timer MBean to perform any operations it needs before being unregistered * by the MBean server. * <P> * Stops the timer. * * @exception java.lang.Exception */ public void preDeregister() throws java.lang.Exception { TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "preDeregister", "stop the timer"); // Stop the timer. // stop(); } /** * Allows the timer MBean to perform any operations needed after having been * unregistered by the MBean server. * <P> * Not used in this context. */ public void postDeregister() { } /* * This overrides the method in NotificationBroadcasterSupport. * Return the MBeanNotificationInfo[] array for this MBean. * The returned array has one element to indicate that the MBean * can emit TimerNotification. The array of type strings * associated with this entry is a snapshot of the current types * that were given to addNotification. */ public synchronized MBeanNotificationInfo[] getNotificationInfo() { Set<String> notifTypes = new TreeSet<String>(); for (Object[] entry : timerTable.values()) { TimerNotification notif = (TimerNotification) entry[TIMER_NOTIF_INDEX]; notifTypes.add(notif.getType()); } String[] notifTypesArray = notifTypes.toArray(new String[0]); return new MBeanNotificationInfo[] { new MBeanNotificationInfo(notifTypesArray, TimerNotification.class.getName(), "Notification sent by Timer MBean") }; } /** * Starts the timer. * <P> * If there is one or more timer notifications before the time in the list of notifications, the notification * is sent according to the <CODE>sendPastNotifications</CODE> flag and then, updated * according to its period and remaining number of occurrences. * If the timer notification date remains earlier than the current date, this notification is just removed * from the list of notifications. */ public synchronized void start() { TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "start", "starting the timer"); // Start the TimerAlarmClock. // if (isActive == false) { timer = new java.util.Timer(); TimerAlarmClock alarmClock; Date date; Date currentDate = new Date(); // Send or not past notifications depending on the flag. // Update the date and the number of occurrences of past notifications // to make them later than the current date. // sendPastNotifications(currentDate, sendPastNotifications); // Update and start all the TimerAlarmClocks. // Here, all the notifications in the timer table are later than the current date. // for (Object[] obj : timerTable.values()) { // Retrieve the date notification and the TimerAlarmClock. // date = (Date)obj[TIMER_DATE_INDEX]; // Update all the TimerAlarmClock timeouts and start them. // boolean fixedRate = ((Boolean)obj[FIXED_RATE_INDEX]).booleanValue(); if (fixedRate) { alarmClock = new TimerAlarmClock(this, date); obj[ALARM_CLOCK_INDEX] = (Object)alarmClock; timer.schedule(alarmClock, alarmClock.next); } else { alarmClock = new TimerAlarmClock(this, (date.getTime() - currentDate.getTime())); obj[ALARM_CLOCK_INDEX] = (Object)alarmClock; timer.schedule(alarmClock, alarmClock.timeout); } } // Set the state to ON. // isActive = true; TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "start", "timer started"); } else { TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "start", "the timer is already activated"); } } /** * Stops the timer. */ public synchronized void stop() { TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "stop", "stopping the timer"); // Stop the TimerAlarmClock. // if (isActive == true) { for (Object[] obj : timerTable.values()) { // Stop all the TimerAlarmClock. // TimerAlarmClock alarmClock = (TimerAlarmClock)obj[ALARM_CLOCK_INDEX]; if (alarmClock != null) {// alarmClock.interrupt();// try {// // Wait until the thread die.// //// alarmClock.join();// } catch (InterruptedException ex) {// // Ignore...// }// // Remove the reference on the TimerAlarmClock.// // alarmClock.cancel(); } } timer.cancel(); // Set the state to OFF. // isActive = false; TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "stop", "timer stopped"); } else { TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "stop", "the timer is already deactivated"); } } /** * Creates a new timer notification with the specified <CODE>type</CODE>, <CODE>message</CODE> * and <CODE>userData</CODE> and inserts it into the list of notifications with a given date, * period and number of occurrences. * <P> * If the timer notification to be inserted has a date that is before the current date, * the method behaves as if the specified date were the current date. <BR> * For once-off notifications, the notification is delivered immediately. <BR> * For periodic notifications, the first notification is delivered immediately and the * subsequent ones are spaced as specified by the period parameter. * <P> * Note that once the timer notification has been added into the list of notifications, * its associated date, period and number of occurrences cannot be updated. * <P> * In the case of a periodic notification, the value of parameter <i>fixedRate</i> is used to * specify the execution scheme, as specified in {@link java.util.Timer}. * * @param type The timer notification type. * @param message The timer notification detailed message. * @param userData The timer notification user data object. * @param date The date when the notification occurs. * @param period The period of the timer notification (in milliseconds). * @param nbOccurences The total number the timer notification will be emitted. * @param fixedRate If <code>true</code> and if the notification is periodic, the notification * is scheduled with a <i>fixed-rate</i> execution scheme. If * <code>false</code> and if the notification is periodic, the notification * is scheduled with a <i>fixed-delay</i> execution scheme. Ignored if the * notification is not periodic. * * @return The identifier of the new created timer notification. * * @exception java.lang.IllegalArgumentException The date is {@code null} or * the period or the number of occurrences is negative. * * @see #addNotification(String, String, Object, Date, long, long) */// NPCTE fix for bugId 4464388, esc 0, MR, to be added after modification of jmx spec// public synchronized Integer addNotification(String type, String message, Serializable userData,// Date date, long period, long nbOccurences)// end of NPCTE fix for bugId 4464388 public synchronized Integer addNotification(String type, String message, Object userData, Date date, long period, long nbOccurences, boolean fixedRate) throws java.lang.IllegalArgumentException { if (date == null) { throw new java.lang.IllegalArgumentException("Timer notification date cannot be null."); } // Check that all the timer notification attributes are valid. // // Invalid timer period value exception: // Check that the period and the nbOccurences are POSITIVE VALUES. // if ((period < 0) || (nbOccurences < 0)) { throw new java.lang.IllegalArgumentException("Negative values for the periodicity"); } Date currentDate = new Date(); // Update the date if it is before the current date. // if (currentDate.after(date)) { date.setTime(currentDate.getTime()); if (TIMER_LOGGER.isLoggable(Level.FINER)) { TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "addNotification", "update timer notification to add with:" + "\n\tNotification date = " + date); } } // Create and add the timer notification into the timer table. // Integer notifID = Integer.valueOf(++counterID); // The sequenceNumber and the timeStamp attributes are updated // when the notification is emitted by the timer. // TimerNotification notif = new TimerNotification(type, this, 0, 0, message, notifID); notif.setUserData(userData); Object[] obj = new Object[6]; TimerAlarmClock alarmClock; if (fixedRate) { alarmClock = new TimerAlarmClock(this, date); } else { alarmClock = new TimerAlarmClock(this, (date.getTime() - currentDate.getTime())); } // Fix bug 00417.B // The date registered into the timer is a clone from the date parameter. // Date d = new Date(date.getTime()); obj[TIMER_NOTIF_INDEX] = (Object)notif; obj[TIMER_DATE_INDEX] = (Object)d; obj[TIMER_PERIOD_INDEX] = (Object) period; obj[TIMER_NB_OCCUR_INDEX] = (Object) nbOccurences; obj[ALARM_CLOCK_INDEX] = (Object)alarmClock; obj[FIXED_RATE_INDEX] = Boolean.valueOf(fixedRate); if (TIMER_LOGGER.isLoggable(Level.FINER)) { StringBuilder strb = new StringBuilder() .append("adding timer notification:\n\t") .append("Notification source = ") .append(notif.getSource()) .append("\n\tNotification type = ") .append(notif.getType()) .append("\n\tNotification ID = ") .append(notifID) .append("\n\tNotification date = ") .append(d)Lines 1–500 of 1292. Load more
/* * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.management.timer; import static com.sun.jmx.defaults.JmxProperties.TIMER_LOGGER; import java.util.ArrayList; import java.util.Date; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.Vector; import java.util.logging.Level; // jmx imports // import javax.management.InstanceNotFoundException; import javax.management.MBeanNotificationInfo; import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.NotificationBroadcasterSupport; import javax.management.ObjectName; /** * * Provides the implementation of the timer MBean. * The timer MBean sends out an alarm at a specified time * that wakes up all the listeners registered to receive timer notifications. * <P> * * This class manages a list of dated timer notifications. * A method allows users to add/remove as many notifications as required. * When a timer notification is emitted by the timer and becomes obsolete, * it is automatically removed from the list of timer notifications. * <BR>Additional timer notifications can be added into regularly repeating notifications. * <P> * * Note: * <OL> * <LI>When sending timer notifications, the timer updates the notification sequence number * irrespective of the notification type. * <LI>The timer service relies on the system date of the host where the <CODE>Timer</CODE> class is loaded. * Listeners may receive untimely notifications * if their host has a different system date. * To avoid such problems, synchronize the system date of all host machines where timing is needed. * <LI>The default behavior for periodic notifications is <i>fixed-delay execution</i>, as * specified in {@link java.util.Timer}. In order to use <i>fixed-rate execution</i>, use the * overloaded {@link #addNotification(String, String, Object, Date, long, long, boolean)} method. * <LI>Notification listeners are potentially all executed in the same * thread. Therefore, they should execute rapidly to avoid holding up * other listeners or perturbing the regularity of fixed-delay * executions. See {@link NotificationBroadcasterSupport}. * </OL> * * @since 1.5 */ public class Timer extends NotificationBroadcasterSupport implements TimerMBean, MBeanRegistration { /* * ------------------------------------------ * PUBLIC VARIABLES * ------------------------------------------ */ /** * Number of milliseconds in one second. * Useful constant for the <CODE>addNotification</CODE> method. */ public static final long ONE_SECOND = 1000; /** * Number of milliseconds in one minute. * Useful constant for the <CODE>addNotification</CODE> method. */ public static final long ONE_MINUTE = 60*ONE_SECOND; /** * Number of milliseconds in one hour. * Useful constant for the <CODE>addNotification</CODE> method. */ public static final long ONE_HOUR = 60*ONE_MINUTE; /** * Number of milliseconds in one day. * Useful constant for the <CODE>addNotification</CODE> method. */ public static final long ONE_DAY = 24*ONE_HOUR; /** * Number of milliseconds in one week. * Useful constant for the <CODE>addNotification</CODE> method. */ public static final long ONE_WEEK = 7*ONE_DAY; /* * ------------------------------------------ * PRIVATE VARIABLES * ------------------------------------------ */ /** * Table containing all the timer notifications of this timer, * with the associated date, period and number of occurrences. */ private Map<Integer,Object[]> timerTable = new Hashtable<Integer,Object[]>(); /** * Past notifications sending on/off flag value. * This attribute is used to specify if the timer has to send past notifications after start. * <BR>The default value is set to <CODE>false</CODE>. */ private boolean sendPastNotifications = false; /** * Timer state. * The default value is set to <CODE>false</CODE>. */ private transient boolean isActive = false; /** * Timer sequence number. * The default value is set to 0. */ private transient long sequenceNumber = 0; // Flags needed to keep the indexes of the objects in the array. // private static final int TIMER_NOTIF_INDEX = 0; private static final int TIMER_DATE_INDEX = 1; private static final int TIMER_PERIOD_INDEX = 2; private static final int TIMER_NB_OCCUR_INDEX = 3; private static final int ALARM_CLOCK_INDEX = 4; private static final int FIXED_RATE_INDEX = 5; /** * The notification counter ID. * Used to keep the max key value inserted into the timer table. */ private int counterID = 0; private java.util.Timer timer; /* * ------------------------------------------ * CONSTRUCTORS * ------------------------------------------ */ /** * Default constructor. */ public Timer() { } /* * ------------------------------------------ * PUBLIC METHODS * ------------------------------------------ */ /** * Allows the timer MBean to perform any operations it needs before being registered * in the MBean server. * <P> * Not used in this context. * * @param server The MBean server in which the timer MBean will be registered. * @param name The object name of the timer MBean. * * @return The name of the timer MBean registered. * * @exception java.lang.Exception */ public ObjectName preRegister(MBeanServer server, ObjectName name) throws java.lang.Exception { return name; } /** * Allows the timer MBean to perform any operations needed after having been * registered in the MBean server or after the registration has failed. * <P> * Not used in this context. */ public void postRegister (Boolean registrationDone) { } /** * Allows the timer MBean to perform any operations it needs before being unregistered * by the MBean server. * <P> * Stops the timer. * * @exception java.lang.Exception */ public void preDeregister() throws java.lang.Exception { TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "preDeregister", "stop the timer"); // Stop the timer. // stop(); } /** * Allows the timer MBean to perform any operations needed after having been * unregistered by the MBean server. * <P> * Not used in this context. */ public void postDeregister() { } /* * This overrides the method in NotificationBroadcasterSupport. * Return the MBeanNotificationInfo[] array for this MBean. * The returned array has one element to indicate that the MBean * can emit TimerNotification. The array of type strings * associated with this entry is a snapshot of the current types * that were given to addNotification. */ public synchronized MBeanNotificationInfo[] getNotificationInfo() { Set<String> notifTypes = new TreeSet<String>(); for (Object[] entry : timerTable.values()) { TimerNotification notif = (TimerNotification) entry[TIMER_NOTIF_INDEX]; notifTypes.add(notif.getType()); } String[] notifTypesArray = notifTypes.toArray(new String[0]); return new MBeanNotificationInfo[] { new MBeanNotificationInfo(notifTypesArray, TimerNotification.class.getName(), "Notification sent by Timer MBean") }; } /** * Starts the timer. * <P> * If there is one or more timer notifications before the time in the list of notifications, the notification * is sent according to the <CODE>sendPastNotifications</CODE> flag and then, updated * according to its period and remaining number of occurrences. * If the timer notification date remains earlier than the current date, this notification is just removed * from the list of notifications. */ public synchronized void start() { TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "start", "starting the timer"); // Start the TimerAlarmClock. // if (isActive == false) { timer = new java.util.Timer(); TimerAlarmClock alarmClock; Date date; Date currentDate = new Date(); // Send or not past notifications depending on the flag. // Update the date and the number of occurrences of past notifications // to make them later than the current date. // sendPastNotifications(currentDate, sendPastNotifications); // Update and start all the TimerAlarmClocks. // Here, all the notifications in the timer table are later than the current date. // for (Object[] obj : timerTable.values()) { // Retrieve the date notification and the TimerAlarmClock. // date = (Date)obj[TIMER_DATE_INDEX]; // Update all the TimerAlarmClock timeouts and start them. // boolean fixedRate = ((Boolean)obj[FIXED_RATE_INDEX]).booleanValue(); if (fixedRate) { alarmClock = new TimerAlarmClock(this, date); obj[ALARM_CLOCK_INDEX] = (Object)alarmClock; timer.schedule(alarmClock, alarmClock.next); } else { alarmClock = new TimerAlarmClock(this, (date.getTime() - currentDate.getTime())); obj[ALARM_CLOCK_INDEX] = (Object)alarmClock; timer.schedule(alarmClock, alarmClock.timeout); } } // Set the state to ON. // isActive = true; TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "start", "timer started"); } else { TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "start", "the timer is already activated"); } } /** * Stops the timer. */ public synchronized void stop() { TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "stop", "stopping the timer"); // Stop the TimerAlarmClock. // if (isActive == true) { for (Object[] obj : timerTable.values()) { // Stop all the TimerAlarmClock. // TimerAlarmClock alarmClock = (TimerAlarmClock)obj[ALARM_CLOCK_INDEX]; if (alarmClock != null) { // alarmClock.interrupt(); // try { // // Wait until the thread die. // // // alarmClock.join(); // } catch (InterruptedException ex) { // // Ignore... // } // // Remove the reference on the TimerAlarmClock. // // alarmClock.cancel(); } } timer.cancel(); // Set the state to OFF. // isActive = false; TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "stop", "timer stopped"); } else { TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "stop", "the timer is already deactivated"); } } /** * Creates a new timer notification with the specified <CODE>type</CODE>, <CODE>message</CODE> * and <CODE>userData</CODE> and inserts it into the list of notifications with a given date, * period and number of occurrences. * <P> * If the timer notification to be inserted has a date that is before the current date, * the method behaves as if the specified date were the current date. <BR> * For once-off notifications, the notification is delivered immediately. <BR> * For periodic notifications, the first notification is delivered immediately and the * subsequent ones are spaced as specified by the period parameter. * <P> * Note that once the timer notification has been added into the list of notifications, * its associated date, period and number of occurrences cannot be updated. * <P> * In the case of a periodic notification, the value of parameter <i>fixedRate</i> is used to * specify the execution scheme, as specified in {@link java.util.Timer}. * * @param type The timer notification type. * @param message The timer notification detailed message. * @param userData The timer notification user data object. * @param date The date when the notification occurs. * @param period The period of the timer notification (in milliseconds). * @param nbOccurences The total number the timer notification will be emitted. * @param fixedRate If <code>true</code> and if the notification is periodic, the notification * is scheduled with a <i>fixed-rate</i> execution scheme. If * <code>false</code> and if the notification is periodic, the notification * is scheduled with a <i>fixed-delay</i> execution scheme. Ignored if the * notification is not periodic. * * @return The identifier of the new created timer notification. * * @exception java.lang.IllegalArgumentException The date is {@code null} or * the period or the number of occurrences is negative. * * @see #addNotification(String, String, Object, Date, long, long) */ // NPCTE fix for bugId 4464388, esc 0, MR, to be added after modification of jmx spec // public synchronized Integer addNotification(String type, String message, Serializable userData, // Date date, long period, long nbOccurences) // end of NPCTE fix for bugId 4464388 public synchronized Integer addNotification(String type, String message, Object userData, Date date, long period, long nbOccurences, boolean fixedRate) throws java.lang.IllegalArgumentException { if (date == null) { throw new java.lang.IllegalArgumentException("Timer notification date cannot be null."); } // Check that all the timer notification attributes are valid. // // Invalid timer period value exception: // Check that the period and the nbOccurences are POSITIVE VALUES. // if ((period < 0) || (nbOccurences < 0)) { throw new java.lang.IllegalArgumentException("Negative values for the periodicity"); } Date currentDate = new Date(); // Update the date if it is before the current date. // if (currentDate.after(date)) { date.setTime(currentDate.getTime()); if (TIMER_LOGGER.isLoggable(Level.FINER)) { TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(), "addNotification", "update timer notification to add with:" + "\n\tNotification date = " + date); } } // Create and add the timer notification into the timer table. // Integer notifID = Integer.valueOf(++counterID); // The sequenceNumber and the timeStamp attributes are updated // when the notification is emitted by the timer. // TimerNotification notif = new TimerNotification(type, this, 0, 0, message, notifID); notif.setUserData(userData); Object[] obj = new Object[6]; TimerAlarmClock alarmClock; if (fixedRate) { alarmClock = new TimerAlarmClock(this, date); } else { alarmClock = new TimerAlarmClock(this, (date.getTime() - currentDate.getTime())); } // Fix bug 00417.B // The date registered into the timer is a clone from the date parameter. // Date d = new Date(date.getTime()); obj[TIMER_NOTIF_INDEX] = (Object)notif; obj[TIMER_DATE_INDEX] = (Object)d; obj[TIMER_PERIOD_INDEX] = (Object) period; obj[TIMER_NB_OCCUR_INDEX] = (Object) nbOccurences; obj[ALARM_CLOCK_INDEX] = (Object)alarmClock; obj[FIXED_RATE_INDEX] = Boolean.valueOf(fixedRate); if (TIMER_LOGGER.isLoggable(Level.FINER)) { StringBuilder strb = new StringBuilder() .append("adding timer notification:\n\t") .append("Notification source = ") .append(notif.getSource()) .append("\n\tNotification type = ") .append(notif.getType()) .append("\n\tNotification ID = ") .append(notifID) .append("\n\tNotification date = ") .append(d)