Save This Page
Home » openjdk-7 » javax » management » timer » [javadoc | source]
    1   /*
    2    * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.management.timer;
   27   
   28   import static com.sun.jmx.defaults.JmxProperties.TIMER_LOGGER;
   29   import java.util.Date;
   30   import java.util.Hashtable;
   31   import java.util.Iterator;
   32   import java.util.Map;
   33   import java.util.Set;
   34   import java.util.TreeSet;
   35   import java.util.Vector;
   36   import java.util.logging.Level;
   37   
   38   // jmx imports
   39   //
   40   import javax.management.InstanceNotFoundException;
   41   import javax.management.MBeanNotificationInfo;
   42   import javax.management.MBeanRegistration;
   43   import javax.management.MBeanServer;
   44   import javax.management.NotificationBroadcasterSupport;
   45   import javax.management.ObjectName;
   46   
   47   /**
   48    *
   49    * Provides the implementation of the timer MBean.
   50    * The timer MBean sends out an alarm at a specified time
   51    * that wakes up all the listeners registered to receive timer notifications.
   52    * <P>
   53    *
   54    * This class manages a list of dated timer notifications.
   55    * A method allows users to add/remove as many notifications as required.
   56    * When a timer notification is emitted by the timer and becomes obsolete,
   57    * it is automatically removed from the list of timer notifications.
   58    * <BR>Additional timer notifications can be added into regularly repeating notifications.
   59    * <P>
   60    *
   61    * Note:
   62    * <OL>
   63    * <LI>When sending timer notifications, the timer updates the notification sequence number
   64    * irrespective of the notification type.
   65    * <LI>The timer service relies on the system date of the host where the <CODE>Timer</CODE> class is loaded.
   66    * Listeners may receive untimely notifications
   67    * if their host has a different system date.
   68    * To avoid such problems, synchronize the system date of all host machines where timing is needed.
   69    * <LI>The default behavior for periodic notifications is <i>fixed-delay execution</i>, as
   70    *     specified in {@link java.util.Timer}. In order to use <i>fixed-rate execution</i>, use the
   71    *     overloaded {@link #addNotification(String, String, Object, Date, long, long, boolean)} method.
   72    * <LI>Notification listeners are potentially all executed in the same
   73    * thread.  Therefore, they should execute rapidly to avoid holding up
   74    * other listeners or perturbing the regularity of fixed-delay
   75    * executions.  See {@link NotificationBroadcasterSupport}.
   76    * </OL>
   77    *
   78    * @since 1.5
   79    */
   80   public class Timer extends NotificationBroadcasterSupport
   81           implements TimerMBean, MBeanRegistration {
   82   
   83   
   84       /*
   85        * ------------------------------------------
   86        *  PUBLIC VARIABLES
   87        * ------------------------------------------
   88        */
   89   
   90       /**
   91        * Number of milliseconds in one second.
   92        * Useful constant for the <CODE>addNotification</CODE> method.
   93        */
   94       public static final long ONE_SECOND = 1000;
   95   
   96       /**
   97        * Number of milliseconds in one minute.
   98        * Useful constant for the <CODE>addNotification</CODE> method.
   99        */
  100       public static final long ONE_MINUTE = 60*ONE_SECOND;
  101   
  102       /**
  103        * Number of milliseconds in one hour.
  104        * Useful constant for the <CODE>addNotification</CODE> method.
  105        */
  106       public static final long ONE_HOUR   = 60*ONE_MINUTE;
  107   
  108       /**
  109        * Number of milliseconds in one day.
  110        * Useful constant for the <CODE>addNotification</CODE> method.
  111        */
  112       public static final long ONE_DAY    = 24*ONE_HOUR;
  113   
  114       /**
  115        * Number of milliseconds in one week.
  116        * Useful constant for the <CODE>addNotification</CODE> method.
  117        */
  118       public static final long ONE_WEEK   = 7*ONE_DAY;
  119   
  120       /*
  121        * ------------------------------------------
  122        *  PRIVATE VARIABLES
  123        * ------------------------------------------
  124        */
  125   
  126       /**
  127        * Table containing all the timer notifications of this timer,
  128        * with the associated date, period and number of occurrences.
  129        */
  130       private Map<Integer,Object[]> timerTable =
  131           new Hashtable<Integer,Object[]>();
  132   
  133       /**
  134        * Past notifications sending on/off flag value.
  135        * This attribute is used to specify if the timer has to send past notifications after start.
  136        * <BR>The default value is set to <CODE>false</CODE>.
  137        */
  138       private boolean sendPastNotifications = false;
  139   
  140       /**
  141        * Timer state.
  142        * The default value is set to <CODE>false</CODE>.
  143        */
  144       private transient boolean isActive = false;
  145   
  146       /**
  147        * Timer sequence number.
  148        * The default value is set to 0.
  149        */
  150       private transient long sequenceNumber = 0;
  151   
  152       // Flags needed to keep the indexes of the objects in the array.
  153       //
  154       private static final int TIMER_NOTIF_INDEX     = 0;
  155       private static final int TIMER_DATE_INDEX      = 1;
  156       private static final int TIMER_PERIOD_INDEX    = 2;
  157       private static final int TIMER_NB_OCCUR_INDEX  = 3;
  158       private static final int ALARM_CLOCK_INDEX     = 4;
  159       private static final int FIXED_RATE_INDEX      = 5;
  160   
  161       /**
  162        * The notification counter ID.
  163        * Used to keep the max key value inserted into the timer table.
  164        */
  165       private int counterID = 0;
  166   
  167       private java.util.Timer timer;
  168   
  169       /*
  170        * ------------------------------------------
  171        *  CONSTRUCTORS
  172        * ------------------------------------------
  173        */
  174   
  175       /**
  176        * Default constructor.
  177        */
  178       public Timer() {
  179       }
  180   
  181       /*
  182        * ------------------------------------------
  183        *  PUBLIC METHODS
  184        * ------------------------------------------
  185        */
  186   
  187       /**
  188        * Allows the timer MBean to perform any operations it needs before being registered
  189        * in the MBean server.
  190        * <P>
  191        * Not used in this context.
  192        *
  193        * @param server The MBean server in which the timer MBean will be registered.
  194        * @param name The object name of the timer MBean.
  195        *
  196        * @return The name of the timer MBean registered.
  197        *
  198        * @exception java.lang.Exception
  199        */
  200       public ObjectName preRegister(MBeanServer server, ObjectName name)
  201           throws java.lang.Exception {
  202           return name;
  203       }
  204   
  205       /**
  206        * Allows the timer MBean to perform any operations needed after having been
  207        * registered in the MBean server or after the registration has failed.
  208        * <P>
  209        * Not used in this context.
  210        */
  211       public void postRegister (Boolean registrationDone) {
  212       }
  213   
  214       /**
  215        * Allows the timer MBean to perform any operations it needs before being unregistered
  216        * by the MBean server.
  217        * <P>
  218        * Stops the timer.
  219        *
  220        * @exception java.lang.Exception
  221        */
  222       public void preDeregister() throws java.lang.Exception {
  223   
  224           TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  225                   "preDeregister", "stop the timer");
  226   
  227           // Stop the timer.
  228           //
  229           stop();
  230       }
  231   
  232       /**
  233        * Allows the timer MBean to perform any operations needed after having been
  234        * unregistered by the MBean server.
  235        * <P>
  236        * Not used in this context.
  237        */
  238       public void postDeregister() {
  239       }
  240   
  241       /*
  242        * This overrides the method in NotificationBroadcasterSupport.
  243        * Return the MBeanNotificationInfo[] array for this MBean.
  244        * The returned array has one element to indicate that the MBean
  245        * can emit TimerNotification.  The array of type strings
  246        * associated with this entry is a snapshot of the current types
  247        * that were given to addNotification.
  248        */
  249       public synchronized MBeanNotificationInfo[] getNotificationInfo() {
  250           Set<String> notifTypes = new TreeSet<String>();
  251           for (Iterator it = timerTable.values().iterator(); it.hasNext(); ) {
  252               Object[] entry = (Object[]) it.next();
  253               TimerNotification notif = (TimerNotification)
  254                   entry[TIMER_NOTIF_INDEX];
  255               notifTypes.add(notif.getType());
  256           }
  257           String[] notifTypesArray =
  258               notifTypes.toArray(new String[0]);
  259           return new MBeanNotificationInfo[] {
  260               new MBeanNotificationInfo(notifTypesArray,
  261                                         TimerNotification.class.getName(),
  262                                         "Notification sent by Timer MBean")
  263           };
  264       }
  265   
  266       /**
  267        * Starts the timer.
  268        * <P>
  269        * If there is one or more timer notifications before the time in the list of notifications, the notification
  270        * is sent according to the <CODE>sendPastNotifications</CODE> flag and then, updated
  271        * according to its period and remaining number of occurrences.
  272        * If the timer notification date remains earlier than the current date, this notification is just removed
  273        * from the list of notifications.
  274        */
  275       public synchronized void start() {
  276   
  277           TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  278                   "start", "starting the timer");
  279   
  280           // Start the TimerAlarmClock.
  281           //
  282           if (isActive == false) {
  283   
  284               timer = new java.util.Timer();
  285   
  286               TimerAlarmClock alarmClock;
  287               Date date;
  288   
  289               Date currentDate = new Date();
  290   
  291               // Send or not past notifications depending on the flag.
  292               // Update the date and the number of occurrences of past notifications
  293               // to make them later than the current date.
  294               //
  295               sendPastNotifications(currentDate, sendPastNotifications);
  296   
  297               // Update and start all the TimerAlarmClocks.
  298               // Here, all the notifications in the timer table are later than the current date.
  299               //
  300               for (Object[] obj : timerTable.values()) {
  301   
  302                   // Retrieve the date notification and the TimerAlarmClock.
  303                   //
  304                   date = (Date)obj[TIMER_DATE_INDEX];
  305   
  306                   // Update all the TimerAlarmClock timeouts and start them.
  307                   //
  308                   boolean fixedRate = ((Boolean)obj[FIXED_RATE_INDEX]).booleanValue();
  309                   if (fixedRate)
  310                   {
  311                     alarmClock = new TimerAlarmClock(this, date);
  312                     obj[ALARM_CLOCK_INDEX] = (Object)alarmClock;
  313                     timer.schedule(alarmClock, alarmClock.next);
  314                   }
  315                   else
  316                   {
  317                     alarmClock = new TimerAlarmClock(this, (date.getTime() - currentDate.getTime()));
  318                     obj[ALARM_CLOCK_INDEX] = (Object)alarmClock;
  319                     timer.schedule(alarmClock, alarmClock.timeout);
  320                   }
  321               }
  322   
  323               // Set the state to ON.
  324               //
  325               isActive = true;
  326   
  327               TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  328                       "start", "timer started");
  329           } else {
  330               TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  331                       "start", "the timer is already activated");
  332           }
  333       }
  334   
  335       /**
  336        * Stops the timer.
  337        */
  338       public synchronized void stop() {
  339   
  340           TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  341                   "stop", "stopping the timer");
  342   
  343           // Stop the TimerAlarmClock.
  344           //
  345           if (isActive == true) {
  346   
  347               for (Object[] obj : timerTable.values()) {
  348   
  349                   // Stop all the TimerAlarmClock.
  350                   //
  351                   TimerAlarmClock alarmClock = (TimerAlarmClock)obj[ALARM_CLOCK_INDEX];
  352                   if (alarmClock != null) {
  353   //                     alarmClock.interrupt();
  354   //                     try {
  355   //                         // Wait until the thread die.
  356   //                         //
  357   //                         alarmClock.join();
  358   //                     } catch (InterruptedException ex) {
  359   //                         // Ignore...
  360   //                     }
  361   //                     // Remove the reference on the TimerAlarmClock.
  362   //                     //
  363   
  364                       alarmClock.cancel();
  365                   }
  366               }
  367   
  368               timer.cancel();
  369   
  370               // Set the state to OFF.
  371               //
  372               isActive = false;
  373   
  374               TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  375                       "stop", "timer stopped");
  376           } else {
  377               TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  378                       "stop", "the timer is already deactivated");
  379           }
  380       }
  381   
  382       /**
  383        * Creates a new timer notification with the specified <CODE>type</CODE>, <CODE>message</CODE>
  384        * and <CODE>userData</CODE> and inserts it into the list of notifications with a given date,
  385        * period and number of occurrences.
  386        * <P>
  387        * If the timer notification to be inserted has a date that is before the current date,
  388        * the method behaves as if the specified date were the current date. <BR>
  389        * For once-off notifications, the notification is delivered immediately. <BR>
  390        * For periodic notifications, the first notification is delivered immediately and the
  391        * subsequent ones are spaced as specified by the period parameter.
  392        * <P>
  393        * Note that once the timer notification has been added into the list of notifications,
  394        * its associated date, period and number of occurrences cannot be updated.
  395        * <P>
  396        * In the case of a periodic notification, the value of parameter <i>fixedRate</i> is used to
  397        * specify the execution scheme, as specified in {@link java.util.Timer}.
  398        *
  399        * @param type The timer notification type.
  400        * @param message The timer notification detailed message.
  401        * @param userData The timer notification user data object.
  402        * @param date The date when the notification occurs.
  403        * @param period The period of the timer notification (in milliseconds).
  404        * @param nbOccurences The total number the timer notification will be emitted.
  405        * @param fixedRate If <code>true</code> and if the notification is periodic, the notification
  406        *                  is scheduled with a <i>fixed-rate</i> execution scheme. If
  407        *                  <code>false</code> and if the notification is periodic, the notification
  408        *                  is scheduled with a <i>fixed-delay</i> execution scheme. Ignored if the
  409        *                  notification is not periodic.
  410        *
  411        * @return The identifier of the new created timer notification.
  412        *
  413        * @exception java.lang.IllegalArgumentException The date is {@code null} or
  414        * the period or the number of occurrences is negative.
  415        *
  416        * @see #addNotification(String, String, Object, Date, long, long)
  417        */
  418   // NPCTE fix for bugId 4464388, esc 0,  MR, to be added after modification of jmx spec
  419   //  public synchronized Integer addNotification(String type, String message, Serializable userData,
  420   //                                                Date date, long period, long nbOccurences)
  421   // end of NPCTE fix for bugId 4464388
  422   
  423       public synchronized Integer addNotification(String type, String message, Object userData,
  424                                                   Date date, long period, long nbOccurences, boolean fixedRate)
  425           throws java.lang.IllegalArgumentException {
  426   
  427           if (date == null) {
  428               throw new java.lang.IllegalArgumentException("Timer notification date cannot be null.");
  429           }
  430   
  431           // Check that all the timer notification attributes are valid.
  432           //
  433   
  434           // Invalid timer period value exception:
  435           // Check that the period and the nbOccurences are POSITIVE VALUES.
  436           //
  437           if ((period < 0) || (nbOccurences < 0)) {
  438               throw new java.lang.IllegalArgumentException("Negative values for the periodicity");
  439           }
  440   
  441           Date currentDate = new Date();
  442   
  443           // Update the date if it is before the current date.
  444           //
  445           if (currentDate.after(date)) {
  446   
  447               date.setTime(currentDate.getTime());
  448               if (TIMER_LOGGER.isLoggable(Level.FINER)) {
  449                   TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  450                           "addNotification",
  451                           "update timer notification to add with:" +
  452                           "\n\tNotification date = " + date);
  453               }
  454           }
  455   
  456           // Create and add the timer notification into the timer table.
  457           //
  458           Integer notifID = Integer.valueOf(++counterID);
  459   
  460           // The sequenceNumber and the timeStamp attributes are updated
  461           // when the notification is emitted by the timer.
  462           //
  463           TimerNotification notif = new TimerNotification(type, this, 0, 0, message, notifID);
  464           notif.setUserData(userData);
  465   
  466           Object[] obj = new Object[6];
  467   
  468           TimerAlarmClock alarmClock;
  469           if (fixedRate)
  470           {
  471             alarmClock = new TimerAlarmClock(this, date);
  472           }
  473           else
  474           {
  475             alarmClock = new TimerAlarmClock(this, (date.getTime() - currentDate.getTime()));
  476           }
  477   
  478           // Fix bug 00417.B
  479           // The date registered into the timer is a clone from the date parameter.
  480           //
  481           Date d = new Date(date.getTime());
  482   
  483           obj[TIMER_NOTIF_INDEX] = (Object)notif;
  484           obj[TIMER_DATE_INDEX] = (Object)d;
  485           obj[TIMER_PERIOD_INDEX] = (Object) period;
  486           obj[TIMER_NB_OCCUR_INDEX] = (Object) nbOccurences;
  487           obj[ALARM_CLOCK_INDEX] = (Object)alarmClock;
  488           obj[FIXED_RATE_INDEX] = Boolean.valueOf(fixedRate);
  489   
  490           if (TIMER_LOGGER.isLoggable(Level.FINER)) {
  491               StringBuilder strb = new StringBuilder()
  492               .append("adding timer notification:\n\t")
  493               .append("Notification source = ")
  494               .append(notif.getSource())
  495               .append("\n\tNotification type = ")
  496               .append(notif.getType())
  497               .append("\n\tNotification ID = ")
  498               .append(notifID)
  499               .append("\n\tNotification date = ")
  500               .append(d)
  501               .append("\n\tNotification period = ")
  502               .append(period)
  503               .append("\n\tNotification nb of occurrences = ")
  504               .append(nbOccurences)
  505               .append("\n\tNotification executes at fixed rate = ")
  506               .append(fixedRate);
  507               TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  508                       "addNotification", strb.toString());
  509           }
  510   
  511           timerTable.put(notifID, obj);
  512   
  513           // Update and start the TimerAlarmClock.
  514           //
  515           if (isActive == true) {
  516             if (fixedRate)
  517             {
  518               timer.schedule(alarmClock, alarmClock.next);
  519             }
  520             else
  521             {
  522               timer.schedule(alarmClock, alarmClock.timeout);
  523             }
  524           }
  525   
  526           TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  527                   "addNotification", "timer notification added");
  528           return notifID;
  529       }
  530   
  531       /**
  532        * Creates a new timer notification with the specified <CODE>type</CODE>, <CODE>message</CODE>
  533        * and <CODE>userData</CODE> and inserts it into the list of notifications with a given date,
  534        * period and number of occurrences.
  535        * <P>
  536        * If the timer notification to be inserted has a date that is before the current date,
  537        * the method behaves as if the specified date were the current date. <BR>
  538        * For once-off notifications, the notification is delivered immediately. <BR>
  539        * For periodic notifications, the first notification is delivered immediately and the
  540        * subsequent ones are spaced as specified by the period parameter.
  541        * <P>
  542        * Note that once the timer notification has been added into the list of notifications,
  543        * its associated date, period and number of occurrences cannot be updated.
  544        * <P>
  545        * In the case of a periodic notification, uses a <i>fixed-delay</i> execution scheme, as specified in
  546        * {@link java.util.Timer}. In order to use a <i>fixed-rate</i> execution scheme, use
  547        * {@link #addNotification(String, String, Object, Date, long, long, boolean)} instead.
  548        *
  549        * @param type The timer notification type.
  550        * @param message The timer notification detailed message.
  551        * @param userData The timer notification user data object.
  552        * @param date The date when the notification occurs.
  553        * @param period The period of the timer notification (in milliseconds).
  554        * @param nbOccurences The total number the timer notification will be emitted.
  555        *
  556        * @return The identifier of the new created timer notification.
  557        *
  558        * @exception java.lang.IllegalArgumentException The date is {@code null} or
  559        * the period or the number of occurrences is negative.
  560        *
  561        * @see #addNotification(String, String, Object, Date, long, long, boolean)
  562        */
  563   // NPCTE fix for bugId 4464388, esc 0,  MR , to be added after modification of jmx spec
  564   //  public synchronized Integer addNotification(String type, String message, Serializable userData,
  565   //                                              Date date, long period)
  566   // end of NPCTE fix for bugId 4464388 */
  567   
  568       public synchronized Integer addNotification(String type, String message, Object userData,
  569                                                   Date date, long period, long nbOccurences)
  570           throws java.lang.IllegalArgumentException {
  571   
  572         return addNotification(type, message, userData, date, period, nbOccurences, false);
  573       }
  574   
  575       /**
  576        * Creates a new timer notification with the specified <CODE>type</CODE>, <CODE>message</CODE>
  577        * and <CODE>userData</CODE> and inserts it into the list of notifications with a given date
  578        * and period and a null number of occurrences.
  579        * <P>
  580        * The timer notification will repeat continuously using the timer period using a <i>fixed-delay</i>
  581        * execution scheme, as specified in {@link java.util.Timer}. In order to use a <i>fixed-rate</i>
  582        * execution scheme, use {@link #addNotification(String, String, Object, Date, long, long,
  583        * boolean)} instead.
  584        * <P>
  585        * If the timer notification to be inserted has a date that is before the current date,
  586        * the method behaves as if the specified date were the current date. The
  587        * first notification is delivered immediately and the subsequent ones are
  588        * spaced as specified by the period parameter.
  589        *
  590        * @param type The timer notification type.
  591        * @param message The timer notification detailed message.
  592        * @param userData The timer notification user data object.
  593        * @param date The date when the notification occurs.
  594        * @param period The period of the timer notification (in milliseconds).
  595        *
  596        * @return The identifier of the new created timer notification.
  597        *
  598        * @exception java.lang.IllegalArgumentException The date is {@code null} or
  599        * the period is negative.
  600        */
  601   // NPCTE fix for bugId 4464388, esc 0,  MR , to be added after modification of jmx spec
  602   //  public synchronized Integer addNotification(String type, String message, Serializable userData,
  603   //                                              Date date, long period)
  604   // end of NPCTE fix for bugId 4464388 */
  605   
  606       public synchronized Integer addNotification(String type, String message, Object userData,
  607                                                   Date date, long period)
  608           throws java.lang.IllegalArgumentException {
  609   
  610           return (addNotification(type, message, userData, date, period, 0));
  611       }
  612   
  613       /**
  614        * Creates a new timer notification with the specified <CODE>type</CODE>, <CODE>message</CODE>
  615        * and <CODE>userData</CODE> and inserts it into the list of notifications with a given date
  616        * and a null period and number of occurrences.
  617        * <P>
  618        * The timer notification will be handled once at the specified date.
  619        * <P>
  620        * If the timer notification to be inserted has a date that is before the current date,
  621        * the method behaves as if the specified date were the current date and the
  622        * notification is delivered immediately.
  623        *
  624        * @param type The timer notification type.
  625        * @param message The timer notification detailed message.
  626        * @param userData The timer notification user data object.
  627        * @param date The date when the notification occurs.
  628        *
  629        * @return The identifier of the new created timer notification.
  630        *
  631        * @exception java.lang.IllegalArgumentException The date is {@code null}.
  632        */
  633   // NPCTE fix for bugId 4464388, esc 0,  MR, to be added after modification of jmx spec
  634   //  public synchronized Integer addNotification(String type, String message, Serializable userData, Date date)
  635   //      throws java.lang.IllegalArgumentException {
  636   // end of NPCTE fix for bugId 4464388
  637   
  638       public synchronized Integer addNotification(String type, String message, Object userData, Date date)
  639           throws java.lang.IllegalArgumentException {
  640   
  641   
  642           return (addNotification(type, message, userData, date, 0, 0));
  643       }
  644   
  645       /**
  646        * Removes the timer notification corresponding to the specified identifier from the list of notifications.
  647        *
  648        * @param id The timer notification identifier.
  649        *
  650        * @exception InstanceNotFoundException The specified identifier does not correspond to any timer notification
  651        * in the list of notifications of this timer MBean.
  652        */
  653       public synchronized void removeNotification(Integer id) throws InstanceNotFoundException {
  654   
  655           // Check that the notification to remove is effectively in the timer table.
  656           //
  657           if (timerTable.containsKey(id) == false) {
  658               throw new InstanceNotFoundException("Timer notification to remove not in the list of notifications");
  659           }
  660   
  661           // Stop the TimerAlarmClock.
  662           //
  663           Object[] obj = timerTable.get(id);
  664           TimerAlarmClock alarmClock = (TimerAlarmClock)obj[ALARM_CLOCK_INDEX];
  665           if (alarmClock != null) {
  666   //             alarmClock.interrupt();
  667   //             try {
  668   //                 // Wait until the thread die.
  669   //                 //
  670   //                 alarmClock.join();
  671   //             } catch (InterruptedException e) {
  672   //                 // Ignore...
  673   //             }
  674   //             // Remove the reference on the TimerAlarmClock.
  675   //             //
  676               alarmClock.cancel();
  677           }
  678   
  679           // Remove the timer notification from the timer table.
  680           //
  681           if (TIMER_LOGGER.isLoggable(Level.FINER)) {
  682               StringBuilder strb = new StringBuilder()
  683               .append("removing timer notification:")
  684               .append("\n\tNotification source = ")
  685               .append(((TimerNotification)obj[TIMER_NOTIF_INDEX]).getSource())
  686               .append("\n\tNotification type = ")
  687               .append(((TimerNotification)obj[TIMER_NOTIF_INDEX]).getType())
  688               .append("\n\tNotification ID = ")
  689               .append(((TimerNotification)obj[TIMER_NOTIF_INDEX]).getNotificationID())
  690               .append("\n\tNotification date = ")
  691               .append(obj[TIMER_DATE_INDEX])
  692               .append("\n\tNotification period = ")
  693               .append(obj[TIMER_PERIOD_INDEX])
  694               .append("\n\tNotification nb of occurrences = ")
  695               .append(obj[TIMER_NB_OCCUR_INDEX])
  696               .append("\n\tNotification executes at fixed rate = ")
  697               .append(obj[FIXED_RATE_INDEX]);
  698               TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  699                       "removeNotification", strb.toString());
  700           }
  701   
  702           timerTable.remove(id);
  703   
  704           TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  705                   "removeNotification", "timer notification removed");
  706       }
  707   
  708       /**
  709        * Removes all the timer notifications corresponding to the specified type from the list of notifications.
  710        *
  711        * @param type The timer notification type.
  712        *
  713        * @exception InstanceNotFoundException The specified type does not correspond to any timer notification
  714        * in the list of notifications of this timer MBean.
  715        */
  716       public synchronized void removeNotifications(String type) throws InstanceNotFoundException {
  717   
  718           Vector<Integer> v = getNotificationIDs(type);
  719   
  720           if (v.isEmpty())
  721               throw new InstanceNotFoundException("Timer notifications to remove not in the list of notifications");
  722   
  723           for (Integer i : v)
  724               removeNotification(i);
  725       }
  726   
  727       /**
  728        * Removes all the timer notifications from the list of notifications
  729        * and resets the counter used to update the timer notification identifiers.
  730        */
  731       public synchronized void removeAllNotifications() {
  732   
  733           TimerAlarmClock alarmClock;
  734   
  735           for (Object[] obj : timerTable.values()) {
  736   
  737               // Stop the TimerAlarmClock.
  738               //
  739               alarmClock = (TimerAlarmClock)obj[ALARM_CLOCK_INDEX];
  740   //             if (alarmClock != null) {
  741   //                 alarmClock.interrupt();
  742   //                 try {
  743   //                     // Wait until the thread die.
  744   //                     //
  745   //                     alarmClock.join();
  746   //                 } catch (InterruptedException ex) {
  747   //                     // Ignore...
  748   //                 }
  749                     // Remove the reference on the TimerAlarmClock.
  750                     //
  751   //             }
  752               alarmClock.cancel();
  753           }
  754   
  755           // Remove all the timer notifications from the timer table.
  756           TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  757                   "removeAllNotifications", "removing all timer notifications");
  758   
  759           timerTable.clear();
  760   
  761           TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  762                   "removeAllNotifications", "all timer notifications removed");
  763           // Reset the counterID.
  764           //
  765           counterID = 0;
  766   
  767           TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
  768                   "removeAllNotifications", "timer notification counter ID reset");
  769       }
  770   
  771       // GETTERS AND SETTERS
  772       //--------------------
  773   
  774       /**
  775        * Gets the number of timer notifications registered into the list of notifications.
  776        *
  777        * @return The number of timer notifications.
  778        */
  779       public int getNbNotifications() {
  780           return timerTable.size();
  781       }
  782   
  783       /**
  784        * Gets all timer notification identifiers registered into the list of notifications.
  785        *
  786        * @return A vector of <CODE>Integer</CODE> objects containing all the timer notification identifiers.
  787        * <BR>The vector is empty if there is no timer notification registered for this timer MBean.
  788        */
  789       public synchronized Vector<Integer> getAllNotificationIDs() {
  790           return new Vector<Integer>(timerTable.keySet());
  791       }
  792   
  793       /**
  794        * Gets all the identifiers of timer notifications corresponding to the specified type.
  795        *
  796        * @param type The timer notification type.
  797        *
  798        * @return A vector of <CODE>Integer</CODE> objects containing all the identifiers of
  799        * timer notifications with the specified <CODE>type</CODE>.
  800        * <BR>The vector is empty if there is no timer notifications registered for this timer MBean
  801        * with the specified <CODE>type</CODE>.
  802        */
  803       public synchronized Vector<Integer> getNotificationIDs(String type) {
  804   
  805           String s;
  806   
  807           Vector<Integer> v = new Vector<Integer>();
  808   
  809           for (Map.Entry<Integer,Object[]> entry : timerTable.entrySet()) {
  810               Object[] obj = entry.getValue();
  811               s = ((TimerNotification)obj[TIMER_NOTIF_INDEX]).getType();
  812               if ((type == null) ? s == null : type.equals(s))
  813                   v.addElement(entry.getKey());
  814           }
  815           return v;
  816       }
  817       // 5089997: return is Vector<Integer> not Vector<TimerNotification>
  818   
  819       /**
  820        * Gets the timer notification type corresponding to the specified identifier.
  821        *
  822        * @param id The timer notification identifier.
  823        *
  824        * @return The timer notification type or null if the identifier is not mapped to any
  825        * timer notification registered for this timer MBean.
  826        */
  827       public String getNotificationType(Integer id) {
  828   
  829           Object[] obj = timerTable.get(id);
  830           if (obj != null) {
  831               return ( ((TimerNotification)obj[TIMER_NOTIF_INDEX]).getType() );
  832           }
  833           return null;
  834       }
  835   
  836       /**
  837        * Gets the timer notification detailed message corresponding to the specified identifier.
  838        *
  839        * @param id The timer notification identifier.
  840        *
  841        * @return The timer notification detailed message or null if the identifier is not mapped to any
  842        * timer notification registered for this timer MBean.
  843        */
  844       public String getNotificationMessage(Integer id) {
  845   
  846           Object[] obj = timerTable.get(id);
  847           if (obj != null) {
  848               return ( ((TimerNotification)obj[TIMER_NOTIF_INDEX]).getMessage() );
  849           }
  850           return null;
  851       }
  852   
  853       /**
  854        * Gets the timer notification user data object corresponding to the specified identifier.
  855        *
  856        * @param id The timer notification identifier.
  857        *
  858        * @return The timer notification user data object or null if the identifier is not mapped to any
  859        * timer notification registered for this timer MBean.
  860        */
  861       // NPCTE fix for bugId 4464388, esc 0, MR, 03 sept 2001, to be added after modification of jmx spec
  862       //public Serializable getNotificationUserData(Integer id) {
  863       // end of NPCTE fix for bugId 4464388
  864   
  865       public Object getNotificationUserData(Integer id) {
  866           Object[] obj = timerTable.get(id);
  867           if (obj != null) {
  868               return ( ((TimerNotification)obj[TIMER_NOTIF_INDEX]).getUserData() );
  869           }
  870           return null;
  871       }
  872   
  873       /**
  874        * Gets a copy of the date associated to a timer notification.
  875        *
  876        * @param id The timer notification identifier.
  877        *
  878        * @return A copy of the date or null if the identifier is not mapped to any
  879        * timer notification registered for this timer MBean.
  880        */
  881       public Date getDate(Integer id) {
  882   
  883           Object[] obj = timerTable.get(id);
  884           if (obj != null) {
  885               Date date = (Date)obj[TIMER_DATE_INDEX];
  886               return (new Date(date.getTime()));
  887           }
  888           return null;
  889       }
  890   
  891       /**
  892        * Gets a copy of the period (in milliseconds) associated to a timer notification.
  893        *
  894        * @param id The timer notification identifier.
  895        *
  896        * @return A copy of the period or null if the identifier is not mapped to any
  897        * timer notification registered for this timer MBean.
  898        */
  899       public Long getPeriod(Integer id) {
  900   
  901           Object[] obj = timerTable.get(id);
  902           if (obj != null) {
  903               return (Long)obj[TIMER_PERIOD_INDEX];
  904           }
  905           return null;
  906       }
  907   
  908       /**
  909        * Gets a copy of the remaining number of occurrences associated to a timer notification.
  910        *
  911        * @param id The timer notification identifier.
  912        *
  913        * @return A copy of the remaining number of occurrences or null if the identifier is not mapped to any
  914        * timer notification registered for this timer MBean.
  915        */
  916       public Long getNbOccurences(Integer id) {
  917   
  918           Object[] obj = timerTable.get(id);
  919           if (obj != null) {
  920               return (Long)obj[TIMER_NB_OCCUR_INDEX];
  921           }
  922           return null;
  923       }
  924   
  925       /**
  926        * Gets a copy of the flag indicating whether a periodic notification is
  927        * executed at <i>fixed-delay</i> or at <i>fixed-rate</i>.
  928        *
  929        * @param id The timer notification identifier.
  930        *
  931        * @return A copy of the flag indicating whether a periodic notification is
  932        *         executed at <i>fixed-delay</i> or at <i>fixed-rate</i>.
  933        */
  934       public Boolean getFixedRate(Integer id) {
  935   
  936         Object[] obj = timerTable.get(id);
  937         if (obj != null) {
  938           Boolean fixedRate = (Boolean)obj[FIXED_RATE_INDEX];
  939           return (Boolean.valueOf(fixedRate.booleanValue()));
  940         }
  941         return null;
  942       }
  943   
  944       /**
  945        * Gets the flag indicating whether or not the timer sends past notifications.
  946        * <BR>The default value of the past notifications sending on/off flag is <CODE>false</CODE>.
  947        *
  948        * @return The past notifications sending on/off flag value.
  949        *
  950        * @see #setSendPastNotifications
  951        */
  952       public boolean getSendPastNotifications() {
  953           return sendPastNotifications;
  954       }
  955   
  956       /**
  957        * Sets the flag indicating whether the timer sends past notifications or not.
  958        * <BR>The default value of the past notifications sending on/off flag is <CODE>false</CODE>.
  959        *
  960        * @param value The past notifications sending on/off flag value.
  961        *
  962        * @see #getSendPastNotifications
  963        */
  964       public void setSendPastNotifications(boolean value) {
  965           sendPastNotifications = value;
  966       }
  967   
  968       /**
  969        * Tests whether the timer MBean is active.
  970        * A timer MBean is marked active when the {@link #start start} method is called.
  971        * It becomes inactive when the {@link #stop stop} method is called.
  972        * <BR>The default value of the active on/off flag is <CODE>false</CODE>.
  973        *
  974        * @return <CODE>true</CODE> if the timer MBean is active, <CODE>false</CODE> otherwise.
  975        */
  976       public boolean isActive() {
  977           return isActive;
  978       }
  979   
  980       /**
  981        * Tests whether the list of timer notifications is empty.
  982        *
  983        * @return <CODE>true</CODE> if the list of timer notifications is empty, <CODE>false</CODE> otherwise.
  984        */
  985       public boolean isEmpty() {
  986           return (timerTable.isEmpty());
  987       }
  988   
  989       /*
  990        * ------------------------------------------
  991        *  PRIVATE METHODS
  992        * ------------------------------------------
  993        */
  994   
  995       /**
  996        * Sends or not past notifications depending on the specified flag.
  997        *
  998        * @param currentDate The current date.
  999        * @param currentFlag The flag indicating if past notifications must be sent or not.
 1000        */
 1001       private synchronized void sendPastNotifications(Date currentDate, boolean currentFlag) {
 1002   
 1003           TimerNotification notif;
 1004           Integer notifID;
 1005           Date date;
 1006   
 1007           for (Object[] obj : timerTable.values()) {
 1008   
 1009               // Retrieve the timer notification and the date notification.
 1010               //
 1011               notif = (TimerNotification)obj[TIMER_NOTIF_INDEX];
 1012               notifID = notif.getNotificationID();
 1013               date = (Date)obj[TIMER_DATE_INDEX];
 1014   
 1015               // Update the timer notification while:
 1016               //  - the timer notification date is earlier than the current date
 1017               //  - the timer notification has not been removed from the timer table.
 1018               //
 1019               while ( (currentDate.after(date)) && (timerTable.containsKey(notifID)) ) {
 1020   
 1021                   if (currentFlag == true) {
 1022                       if (TIMER_LOGGER.isLoggable(Level.FINER)) {
 1023                           StringBuilder strb = new StringBuilder()
 1024                           .append("sending past timer notification:")
 1025                           .append("\n\tNotification source = ")
 1026                           .append(notif.getSource())
 1027                           .append("\n\tNotification type = ")
 1028                           .append(notif.getType())
 1029                           .append("\n\tNotification ID = ")
 1030                           .append(notif.getNotificationID())
 1031                           .append("\n\tNotification date = ")
 1032                           .append(date)
 1033                           .append("\n\tNotification period = ")
 1034                           .append(obj[TIMER_PERIOD_INDEX])
 1035                           .append("\n\tNotification nb of occurrences = ")
 1036                           .append(obj[TIMER_NB_OCCUR_INDEX])
 1037                           .append("\n\tNotification executes at fixed rate = ")
 1038                           .append(obj[FIXED_RATE_INDEX]);
 1039                           TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
 1040                                   "sendPastNotifications", strb.toString());
 1041                       }
 1042                       sendNotification(date, notif);
 1043   
 1044                       TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
 1045                               "sendPastNotifications", "past timer notification sent");
 1046                   }
 1047   
 1048                   // Update the date and the number of occurrences of the timer notification.
 1049                   //
 1050                   updateTimerTable(notif.getNotificationID());
 1051               }
 1052           }
 1053       }
 1054   
 1055       /**
 1056        * If the timer notification is not periodic, it is removed from the list of notifications.
 1057        * <P>
 1058        * If the timer period of the timer notification has a non null periodicity,
 1059        * the date of the timer notification is updated by adding the periodicity.
 1060        * The associated TimerAlarmClock is updated by setting its timeout to the period value.
 1061        * <P>
 1062        * If the timer period has a defined number of occurrences, the timer
 1063        * notification is updated if the number of occurrences has not yet been reached.
 1064        * Otherwise it is removed from the list of notifications.
 1065        *
 1066        * @param notifID The timer notification identifier to update.
 1067        */
 1068       private synchronized void updateTimerTable(Integer notifID) {
 1069   
 1070           // Retrieve the timer notification and the TimerAlarmClock.
 1071           //
 1072           Object[] obj = timerTable.get(notifID);
 1073           Date date = (Date)obj[TIMER_DATE_INDEX];
 1074           Long period = (Long)obj[TIMER_PERIOD_INDEX];
 1075           Long nbOccurences = (Long)obj[TIMER_NB_OCCUR_INDEX];
 1076           Boolean fixedRate = (Boolean)obj[FIXED_RATE_INDEX];
 1077           TimerAlarmClock alarmClock = (TimerAlarmClock)obj[ALARM_CLOCK_INDEX];
 1078   
 1079           if (period.longValue() != 0) {
 1080   
 1081               // Update the date and the number of occurrences of the timer notification
 1082               // and the TimerAlarmClock time out.
 1083               // NOTES :
 1084               //   nbOccurences = 0 notifies an infinite periodicity.
 1085               //   nbOccurences = 1 notifies a finite periodicity that has reached its end.
 1086               //   nbOccurences > 1 notifies a finite periodicity that has not yet reached its end.
 1087               //
 1088               if ((nbOccurences.longValue() == 0) || (nbOccurences.longValue() > 1)) {
 1089   
 1090                   date.setTime(date.getTime() + period.longValue());
 1091                   obj[TIMER_NB_OCCUR_INDEX] = Long.valueOf(java.lang.Math.max(0L, (nbOccurences.longValue() - 1)));
 1092                   nbOccurences = (Long)obj[TIMER_NB_OCCUR_INDEX];
 1093   
 1094                   if (isActive == true) {
 1095                     if (fixedRate.booleanValue())
 1096                     {
 1097                       alarmClock = new TimerAlarmClock(this, date);
 1098                       obj[ALARM_CLOCK_INDEX] = (Object)alarmClock;
 1099                       timer.schedule(alarmClock, alarmClock.next);
 1100                     }
 1101                     else
 1102                     {
 1103                       alarmClock = new TimerAlarmClock(this, period.longValue());
 1104                       obj[ALARM_CLOCK_INDEX] = (Object)alarmClock;
 1105                       timer.schedule(alarmClock, alarmClock.timeout);
 1106                     }
 1107                   }
 1108                   if (TIMER_LOGGER.isLoggable(Level.FINER)) {
 1109                       TimerNotification notif = (TimerNotification)obj[TIMER_NOTIF_INDEX];
 1110                       StringBuilder strb = new StringBuilder()
 1111                       .append("update timer notification with:")
 1112                       .append("\n\tNotification source = ")
 1113                       .append(notif.getSource())
 1114                       .append("\n\tNotification type = ")
 1115                       .append(notif.getType())
 1116                       .append("\n\tNotification ID = ")
 1117                       .append(notifID)
 1118                       .append("\n\tNotification date = ")
 1119                       .append(date)
 1120                       .append("\n\tNotification period = ")
 1121                       .append(period)
 1122                       .append("\n\tNotification nb of occurrences = ")
 1123                       .append(nbOccurences)
 1124                       .append("\n\tNotification executes at fixed rate = ")
 1125                       .append(fixedRate);
 1126                       TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
 1127                               "updateTimerTable", strb.toString());
 1128                   }
 1129               }
 1130               else {
 1131                   if (alarmClock != null) {
 1132   //                     alarmClock.interrupt();
 1133   //                     try {
 1134   //                         // Wait until the thread die.
 1135   //                         //
 1136   //                         alarmClock.join();
 1137   //                     } catch (InterruptedException e) {
 1138   //                         // Ignore...
 1139   //                     }
 1140                       alarmClock.cancel();
 1141                   }
 1142                   timerTable.remove(notifID);
 1143               }
 1144           }
 1145           else {
 1146               if (alarmClock != null) {
 1147   //                 alarmClock.interrupt();
 1148   //                 try {
 1149   //                     // Wait until the thread die.
 1150   //                     //
 1151   //                     alarmClock.join();
 1152   //                 } catch (InterruptedException e) {
 1153   //                     // Ignore...
 1154   //                 }
 1155   
 1156                      alarmClock.cancel();
 1157               }
 1158               timerTable.remove(notifID);
 1159           }
 1160       }
 1161   
 1162       /*
 1163        * ------------------------------------------
 1164        *  PACKAGE METHODS
 1165        * ------------------------------------------
 1166        */
 1167   
 1168       /**
 1169        * This method is called by the timer each time
 1170        * the TimerAlarmClock has exceeded its timeout.
 1171        *
 1172        * @param notification The TimerAlarmClock notification.
 1173        */
 1174       @SuppressWarnings("deprecation")
 1175       void notifyAlarmClock(TimerAlarmClockNotification notification) {
 1176   
 1177           TimerNotification timerNotification = null;
 1178           Date timerDate = null;
 1179   
 1180           // Retrieve the timer notification associated to the alarm-clock.
 1181           //
 1182           TimerAlarmClock alarmClock = (TimerAlarmClock)notification.getSource();
 1183   
 1184           for (Object[] obj : timerTable.values()) {
 1185               if (obj[ALARM_CLOCK_INDEX] == alarmClock) {
 1186                   timerNotification = (TimerNotification)obj[TIMER_NOTIF_INDEX];
 1187                   timerDate = (Date)obj[TIMER_DATE_INDEX];
 1188                   break;
 1189               }
 1190           }
 1191   
 1192           // Notify the timer.
 1193           //
 1194           sendNotification(timerDate, timerNotification);
 1195   
 1196           // Update the notification and the TimerAlarmClock timeout.
 1197           //
 1198           updateTimerTable(timerNotification.getNotificationID());
 1199       }
 1200   
 1201       /**
 1202        * This method is used by the timer MBean to update and send a timer
 1203        * notification to all the listeners registered for this kind of notification.
 1204        *
 1205        * @param timeStamp The notification emission date.
 1206        * @param notification The timer notification to send.
 1207        */
 1208       void sendNotification(Date timeStamp, TimerNotification notification) {
 1209   
 1210           if (TIMER_LOGGER.isLoggable(Level.FINER)) {
 1211               StringBuilder strb = new StringBuilder()
 1212               .append("sending timer notification:")
 1213               .append("\n\tNotification source = ")
 1214               .append(notification.getSource())
 1215               .append("\n\tNotification type = ")
 1216               .append(notification.getType())
 1217               .append("\n\tNotification ID = ")
 1218               .append(notification.getNotificationID())
 1219               .append("\n\tNotification date = ")
 1220               .append(timeStamp);
 1221               TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
 1222                       "sendNotification", strb.toString());
 1223           }
 1224           long curSeqNumber;
 1225           synchronized(this) {
 1226               sequenceNumber = sequenceNumber + 1;
 1227               curSeqNumber = sequenceNumber;
 1228           }
 1229           synchronized (notification) {
 1230               notification.setTimeStamp(timeStamp.getTime());
 1231               notification.setSequenceNumber(curSeqNumber);
 1232               this.sendNotification((TimerNotification)notification.cloneTimerNotification());
 1233           }
 1234   
 1235           TIMER_LOGGER.logp(Level.FINER, Timer.class.getName(),
 1236                   "sendNotification", "timer notification sent");
 1237       }
 1238   }
 1239   
 1240   /**
 1241    * TimerAlarmClock inner class:
 1242    * This class provides a simple implementation of an alarm clock MBean.
 1243    * The aim of this MBean is to set up an alarm which wakes up the timer every timeout (fixed-delay)
 1244    * or at the specified date (fixed-rate).
 1245    */
 1246   
 1247   class TimerAlarmClock extends java.util.TimerTask {
 1248   
 1249       Timer listener = null;
 1250       long timeout = 10000;
 1251       Date next = null;
 1252   
 1253       /*
 1254        * ------------------------------------------
 1255        *  CONSTRUCTORS
 1256        * ------------------------------------------
 1257        */
 1258   
 1259       public TimerAlarmClock(Timer listener, long timeout) {
 1260           this.listener = listener;
 1261           this.timeout = Math.max(0L, timeout);
 1262       }
 1263   
 1264       public TimerAlarmClock(Timer listener, Date next) {
 1265           this.listener = listener;
 1266           this.next = next;
 1267       }
 1268   
 1269       /*
 1270        * ------------------------------------------
 1271        *  PUBLIC METHODS
 1272        * ------------------------------------------
 1273        */
 1274   
 1275       /**
 1276        * This method is called by the timer when it is started.
 1277        */
 1278       public void run() {
 1279   
 1280           try {
 1281               //this.sleep(timeout);
 1282               TimerAlarmClockNotification notif = new TimerAlarmClockNotification(this);
 1283               listener.notifyAlarmClock(notif);
 1284           } catch (Exception e) {
 1285               TIMER_LOGGER.logp(Level.FINEST, Timer.class.getName(), "run",
 1286                       "Got unexpected exception when sending a notification", e);
 1287           }
 1288       }
 1289   }

Save This Page
Home » openjdk-7 » javax » management » timer » [javadoc | source]