KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > management > timer > Timer


1 /*
2  * @(#)Timer.java 4.58 04/04/13
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.management.timer;
9
10
11
12 // java imports
13
//
14
import java.util.Date JavaDoc;
15 import java.util.Enumeration JavaDoc;
16 import java.util.Hashtable JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.Set JavaDoc;
19 import java.util.TreeSet JavaDoc;
20 import java.util.Vector JavaDoc;
21
22 // jmx imports
23
//
24
import javax.management.MBeanNotificationInfo JavaDoc;
25 import javax.management.MBeanRegistration JavaDoc;
26 import javax.management.MBeanServer JavaDoc;
27 import javax.management.NotificationBroadcasterSupport JavaDoc;
28 import javax.management.ObjectName JavaDoc;
29 import javax.management.InstanceNotFoundException JavaDoc;
30
31 import com.sun.jmx.trace.Trace;
32
33 /**
34  *
35  * Provides the implementation of the timer MBean.
36  * The timer MBean sends out an alarm at a specified time
37  * that wakes up all the listeners registered to receive timer notifications.
38  * <P>
39  *
40  * This class manages a list of dated timer notifications.
41  * A method allows users to add/remove as many notifications as required.
42  * When a timer notification is emitted by the timer and becomes obsolete,
43  * it is automatically removed from the list of timer notifications.
44  * <BR>Additional timer notifications can be added into regularly repeating notifications.
45  * <P>
46  *
47  * Note:
48  * <OL>
49  * <LI>All notifications before the time when the <CODE>addNotification</CODE> method is called
50  * are ignored, irrespective of the <CODE>sendPastNotifications</CODE> flag.
51  * <LI>When sending timer notifications, the timer updates the notification sequence number
52  * irrespective of the notification type.
53  * <LI>The timer service relies on the system date of the host where the <CODE>Timer</CODE> class is loaded.
54  * Listeners may receive untimely notifications
55  * if their host has a different system date.
56  * To avoid such problems, synchronize the system date of all host machines where timing is needed.
57  * <LI>The default behavior for periodic notifications is <i>fixed-delay execution</i>, as
58  * specified in {@link java.util.Timer}. In order to use <i>fixed-rate execution</i>, use the
59  * overloaded {@link #addNotification(String, String, Object, Date, long, long, boolean)} method.
60  * <LI>Notification listeners are potentially all executed in the same
61  * thread. Therefore, they should execute rapidly to avoid holding up
62  * other listeners or perturbing the regularity of fixed-delay
63  * executions. See {@link NotificationBroadcasterSupport}.
64  * </OL>
65  *
66  * @version 4.58 04/13/04
67  * @author Sun Microsystems, Inc
68  *
69  * @since 1.5
70  */

71 public class Timer extends NotificationBroadcasterSupport JavaDoc
72     implements TimerMBean JavaDoc, MBeanRegistration JavaDoc {
73
74     
75     /*
76      * ------------------------------------------
77      * PUBLIC VARIABLES
78      * ------------------------------------------
79      */

80
81     /**
82      * Number of milliseconds in one second.
83      * Useful constant for the <CODE>addNotification</CODE> method.
84      */

85     public static final long ONE_SECOND = 1000;
86
87     /**
88      * Number of milliseconds in one minute.
89      * Useful constant for the <CODE>addNotification</CODE> method.
90      */

91     public static final long ONE_MINUTE = 60*ONE_SECOND;
92
93     /**
94      * Number of milliseconds in one hour.
95      * Useful constant for the <CODE>addNotification</CODE> method.
96      */

97     public static final long ONE_HOUR = 60*ONE_MINUTE;
98
99     /**
100      * Number of milliseconds in one day.
101      * Useful constant for the <CODE>addNotification</CODE> method.
102      */

103     public static final long ONE_DAY = 24*ONE_HOUR;
104
105     /**
106      * Number of milliseconds in one week.
107      * Useful constant for the <CODE>addNotification</CODE> method.
108      */

109     public static final long ONE_WEEK = 7*ONE_DAY;
110
111
112     // TRACES & DEBUG
113
//---------------
114

115     boolean isTraceOn() {
116         return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_TIMER);
117     }
118
119     void trace(String JavaDoc clz, String JavaDoc func, String JavaDoc info) {
120         Trace.send(Trace.LEVEL_TRACE, Trace.INFO_TIMER, clz, func, info);
121     }
122
123     void trace(String JavaDoc func, String JavaDoc info) {
124         trace(dbgTag, func, info);
125     }
126     
127     boolean isDebugOn() {
128         return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_TIMER);
129     }
130
131     void debug(String JavaDoc clz, String JavaDoc func, String JavaDoc info) {
132         Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_TIMER, clz, func, info);
133     }
134
135     void debug(String JavaDoc func, String JavaDoc info) {
136         debug(dbgTag, func, info);
137     }
138     
139
140     /*
141      * ------------------------------------------
142      * PRIVATE VARIABLES
143      * ------------------------------------------
144      */

145
146     private static final String JavaDoc dbgTag = "Timer";
147     
148     /**
149      * Table containing all the timer notifications of this timer,
150      * with the associated date, period and number of occurrences.
151      */

152     private Hashtable JavaDoc timerTable = new Hashtable JavaDoc();
153     
154     /**
155      * Past notifications sending on/off flag value.
156      * This attribute is used to specify if the timer has to send past notifications after start.
157      * <BR>The default value is set to <CODE>false</CODE>.
158      */

159     private boolean sendPastNotifications = false;
160     
161     /**
162      * Timer state.
163      * The default value is set to <CODE>false</CODE>.
164      */

165     private transient boolean isActive = false;
166     
167     /**
168      * Timer sequence number.
169      * The default value is set to 0.
170      */

171     private transient long sequenceNumber = 0;
172     
173     // Flags needed to keep the indexes of the objects in the array.
174
//
175
private static final int TIMER_NOTIF_INDEX = 0;
176     private static final int TIMER_DATE_INDEX = 1;
177     private static final int TIMER_PERIOD_INDEX = 2;
178     private static final int TIMER_NB_OCCUR_INDEX = 3;
179     private static final int ALARM_CLOCK_INDEX = 4;
180     private static final int FIXED_RATE_INDEX = 5;
181
182     /**
183      * The notification counter ID.
184      * Used to keep the max key value inserted into the timer table.
185      */

186     private int counterID = 0;
187
188     private java.util.Timer JavaDoc timer;
189
190     /*
191      * ------------------------------------------
192      * CONSTRUCTORS
193      * ------------------------------------------
194      */

195
196     /**
197      * Default constructor.
198      */

199     public Timer() {
200     }
201   
202     /*
203      * ------------------------------------------
204      * PUBLIC METHODS
205      * ------------------------------------------
206      */

207     
208     /**
209      * Allows the timer MBean to perform any operations it needs before being registered
210      * in the MBean server.
211      * <P>
212      * Not used in this context.
213      *
214      * @param server The MBean server in which the timer MBean will be registered.
215      * @param name The object name of the timer MBean.
216      *
217      * @return The name of the timer MBean registered.
218      *
219      * @exception java.lang.Exception
220      */

221     public ObjectName JavaDoc preRegister(MBeanServer JavaDoc server, ObjectName JavaDoc name)
222         throws java.lang.Exception JavaDoc {
223         return name;
224     }
225             
226     /**
227      * Allows the timer MBean to perform any operations needed after having been
228      * registered in the MBean server or after the registration has failed.
229      * <P>
230      * Not used in this context.
231      */

232     public void postRegister (Boolean JavaDoc registrationDone) {
233     }
234
235     /**
236      * Allows the timer MBean to perform any operations it needs before being unregistered
237      * by the MBean server.
238      * <P>
239      * Stops the timer.
240      *
241      * @exception java.lang.Exception
242      */

243     public void preDeregister() throws java.lang.Exception JavaDoc {
244         
245         if (isTraceOn()) {
246             trace("preDeregister", "stop the timer");
247         }
248         
249         // Stop the timer.
250
//
251
stop();
252     }
253
254     /**
255      * Allows the timer MBean to perform any operations needed after having been
256      * unregistered by the MBean server.
257      * <P>
258      * Not used in this context.
259      */

260     public void postDeregister() {
261     }
262
263     /*
264      * This overrides the method in NotificationBroadcasterSupport.
265      * Return the MBeanNotificationInfo[] array for this MBean.
266      * The returned array has one element to indicate that the MBean
267      * can emit TimerNotification. The array of type strings
268      * associated with this entry is a snapshot of the current types
269      * that were given to addNotification.
270      */

271     public synchronized MBeanNotificationInfo JavaDoc[] getNotificationInfo() {
272     Set JavaDoc/*<String>*/ notifTypes = new TreeSet JavaDoc();
273     for (Iterator JavaDoc it = timerTable.values().iterator(); it.hasNext(); ) {
274         Object JavaDoc[] entry = (Object JavaDoc[]) it.next();
275         TimerNotification JavaDoc notif = (TimerNotification JavaDoc)
276         entry[TIMER_NOTIF_INDEX];
277         notifTypes.add(notif.getType());
278     }
279     String JavaDoc[] notifTypesArray = (String JavaDoc[])
280         notifTypes.toArray(new String JavaDoc[0]);
281     return new MBeanNotificationInfo JavaDoc[] {
282         new MBeanNotificationInfo JavaDoc(notifTypesArray,
283                       TimerNotification JavaDoc.class.getName(),
284                       "Notification sent by Timer MBean")
285     };
286     }
287
288     /**
289      * Starts the timer.
290      * <P>
291      * If there is one or more timer notifications before the time in the list of notifications, the notification
292      * is sent according to the <CODE>sendPastNotifications</CODE> flag and then, updated
293      * according to its period and remaining number of occurrences.
294      * If the timer notification date remains earlier than the current date, this notification is just removed
295      * from the list of notifications.
296      */

297     public synchronized void start() {
298         
299         if (isTraceOn()) {
300             trace("start", "starting the timer");
301         }
302         
303         // Start the TimerAlarmClock.
304
//
305
if (isActive == false) {
306           
307         timer = new java.util.Timer JavaDoc();
308
309             TimerAlarmClock JavaDoc alarmClock;
310             Object JavaDoc[] obj;
311             Date JavaDoc date;
312         
313             Date JavaDoc currentDate = new Date JavaDoc();
314            
315             // Send or not past notifications depending on the flag.
316
// Update the date and the number of occurrences of past notifications
317
// to make them later than the current date.
318
//
319
sendPastNotifications(currentDate, sendPastNotifications);
320            
321             // Update and start all the TimerAlarmClocks.
322
// Here, all the notifications in the timer table are later than the current date.
323
//
324
Enumeration JavaDoc e = timerTable.elements();
325             while (e.hasMoreElements()) {
326                  
327                 obj = (Object JavaDoc[])e.nextElement();
328                  
329                 // Retrieve the date notification and the TimerAlarmClock.
330
//
331
date = (Date JavaDoc)obj[TIMER_DATE_INDEX];
332                  
333                 // Update all the TimerAlarmClock timeouts and start them.
334
//
335
boolean fixedRate = ((Boolean JavaDoc)obj[FIXED_RATE_INDEX]).booleanValue();
336                 if (fixedRate)
337                 {
338                   alarmClock = new TimerAlarmClock JavaDoc(this, date);
339                   obj[ALARM_CLOCK_INDEX] = (Object JavaDoc)alarmClock;
340                   timer.schedule(alarmClock, alarmClock.next);
341                 }
342                 else
343                 {
344                   alarmClock = new TimerAlarmClock JavaDoc(this, (date.getTime() - currentDate.getTime()));
345                   obj[ALARM_CLOCK_INDEX] = (Object JavaDoc)alarmClock;
346                   timer.schedule(alarmClock, alarmClock.timeout);
347                 }
348             }
349            
350             // Set the state to ON.
351
//
352
isActive = true;
353         
354             if (isTraceOn()) {
355                 trace("start", "timer started");
356             }
357         } else {
358             if (isTraceOn()) {
359                 trace("start", "the timer is already activated");
360             }
361         }
362     }
363
364     /**
365      * Stops the timer.
366      */

367     public synchronized void stop() {
368         
369         if (isTraceOn()) {
370             trace("stop", "stoping the timer");
371         }
372         
373         // Stop the TimerAlarmClock.
374
//
375
if (isActive == true) {
376           
377             TimerAlarmClock JavaDoc alarmClock;
378             Object JavaDoc[] obj;
379           
380             Enumeration JavaDoc e = timerTable.elements();
381             while (e.hasMoreElements()) {
382                 
383                 obj = (Object JavaDoc[])e.nextElement();
384                 
385                 // Stop all the TimerAlarmClock.
386
//
387
alarmClock = (TimerAlarmClock JavaDoc)obj[ALARM_CLOCK_INDEX];
388                 if (alarmClock != null) {
389 // alarmClock.interrupt();
390
// try {
391
// // Wait until the thread die.
392
// //
393
// alarmClock.join();
394
// } catch (InterruptedException ex) {
395
// // Ignore...
396
// }
397
// // Remove the reference on the TimerAlarmClock.
398
// //
399

400             alarmClock.cancel();
401                     alarmClock = null;
402                 }
403             }
404           
405             timer.cancel();
406
407             // Set the state to OFF.
408
//
409
isActive = false;
410             
411             if (isTraceOn()) {
412                 trace("stop", "timer stopped");
413             }
414         } else {
415             if (isTraceOn()) {
416                 trace("stop", "the timer is already deactivated");
417             }
418         }
419     }
420             
421     /**
422      * Creates a new timer notification with the specified <CODE>type</CODE>, <CODE>message</CODE>
423      * and <CODE>userData</CODE> and inserts it into the list of notifications with a given date,
424      * period and number of occurrences.
425      * <P>
426      * If the timer notification to be inserted has a date that is before the current date,
427      * the method behaves as if the specified date were the current date. <BR>
428      * For once-off notifications, the notification is delivered immediately. <BR>
429      * For periodic notifications, the first notification is delivered immediately and the
430      * subsequent ones are spaced as specified by the period parameter.
431      * <P>
432      * Note that once the timer notification has been added into the list of notifications,
433      * its associated date, period and number of occurrences cannot be updated.
434      * <P>
435      * In the case of a periodic notification, the value of parameter <i>fixedRate</i> is used to
436      * specify the execution scheme, as specified in {@link java.util.Timer}.
437      *
438      * @param type The timer notification type.
439      * @param message The timer notification detailed message.
440      * @param userData The timer notification user data object.
441      * @param date The date when the notification occurs.
442      * @param period The period of the timer notification (in milliseconds).
443      * @param nbOccurences The total number the timer notification will be emitted.
444      * @param fixedRate If <code>true</code> and if the notification is periodic, the notification
445      * is scheduled with a <i>fixed-rate</i> execution scheme. If
446      * <code>false</code> and if the notification is periodic, the notification
447      * is scheduled with a <i>fixed-delay</i> execution scheme. Ignored if the
448      * notification is not periodic.
449      *
450      * @return The identifier of the new created timer notification.
451      *
452      * @exception java.lang.IllegalArgumentException The period or the number of occurrences is negative
453      *
454      * @see #addNotification(String, String, Object, Date, long, long)
455      */

456 // NPCTE fix for bugId 4464388, esc 0, MR, to be added after modification of jmx spec
457
// public synchronized Integer addNotification(String type, String message, Serializable userData,
458
// Date date, long period, long nbOccurences)
459
// end of NPCTE fix for bugId 4464388
460

461     public synchronized Integer JavaDoc addNotification(String JavaDoc type, String JavaDoc message, Object JavaDoc userData,
462                                                 Date JavaDoc date, long period, long nbOccurences, boolean fixedRate)
463         throws java.lang.IllegalArgumentException JavaDoc {
464         
465         if (date == null) {
466             throw new java.lang.IllegalArgumentException JavaDoc("Timer notification date cannot be null.");
467         }
468         
469         // Check that all the timer notification attributes are valid.
470
//
471

472         // Invalid timer period value exception:
473
// Check that the period and the nbOccurences are POSITIVE VALUES.
474
//
475
if ((period < 0) || (nbOccurences < 0)) {
476             throw new java.lang.IllegalArgumentException JavaDoc("Negative values for the periodicity");
477         }
478         
479         Date JavaDoc currentDate = new Date JavaDoc();
480                         
481         // Update the date if it is before the current date.
482
//
483
if (currentDate.after(date)) {
484             
485           date.setTime(currentDate.getTime());
486           if (isTraceOn()) {
487             trace("addNotification", "update timer notification to add with:" +
488                   "\n\tNotification date = " + date);
489           }
490         }
491           
492         // Create and add the timer notification into the timer table.
493
//
494
Integer JavaDoc notifID = null;
495         notifID = new Integer JavaDoc(++counterID);
496         
497         // The sequenceNumber and the timeStamp attributes are updated
498
// when the notification is emitted by the timer.
499
//
500
TimerNotification JavaDoc notif = new TimerNotification JavaDoc(type, this, 0, 0, message, notifID);
501         notif.setUserData(userData);
502         
503         Object JavaDoc[] obj = new Object JavaDoc[6];
504         
505         TimerAlarmClock JavaDoc alarmClock;
506         if (fixedRate)
507         {
508           alarmClock = new TimerAlarmClock JavaDoc(this, date);
509         }
510         else
511         {
512           alarmClock = new TimerAlarmClock JavaDoc(this, (date.getTime() - currentDate.getTime()));
513         }
514
515         // Fix bug 00417.B
516
// The date registered into the timer is a clone from the date parameter.
517
//
518
Date JavaDoc d = new Date JavaDoc(date.getTime());
519                 
520         obj[TIMER_NOTIF_INDEX] = (Object JavaDoc)notif;
521         obj[TIMER_DATE_INDEX] = (Object JavaDoc)d;
522         obj[TIMER_PERIOD_INDEX] = (Object JavaDoc) new Long JavaDoc(period);
523         obj[TIMER_NB_OCCUR_INDEX] = (Object JavaDoc) new Long JavaDoc(nbOccurences);
524         obj[ALARM_CLOCK_INDEX] = (Object JavaDoc)alarmClock;
525         obj[FIXED_RATE_INDEX] = new Boolean JavaDoc(fixedRate);
526                 
527         if (isTraceOn()) {
528             trace("addNotification", "adding timer notification:" +
529                   "\n\tNotification source = " + notif.getSource() +
530                   "\n\tNotification type = " + notif.getType() +
531                   "\n\tNotification ID = " + notifID +
532                   "\n\tNotification date = " + d +
533                   "\n\tNotification period = " + period +
534                   "\n\tNotification nb of occurrences = " + nbOccurences +
535                   "\n\tNotification executes at fixed rate = " + fixedRate);
536         }
537         
538         timerTable.put(notifID, obj);
539         
540         // Update and start the TimerAlarmClock.
541
//
542
if (isActive == true) {
543           if (fixedRate)
544           {
545         timer.schedule(alarmClock, alarmClock.next);
546           }
547           else
548           {
549             timer.schedule(alarmClock, alarmClock.timeout);
550           }
551         }
552         
553         if (isTraceOn()) {
554             trace("addNotification", "timer notification added");
555         }
556         return notifID;
557     }
558
559     /**
560      * Creates a new timer notification with the specified <CODE>type</CODE>, <CODE>message</CODE>
561      * and <CODE>userData</CODE> and inserts it into the list of notifications with a given date,
562      * period and number of occurrences.
563      * <P>
564      * If the timer notification to be inserted has a date that is before the current date,
565      * the method behaves as if the specified date were the current date. <BR>
566      * For once-off notifications, the notification is delivered immediately. <BR>
567      * For periodic notifications, the first notification is delivered immediately and the
568      * subsequent ones are spaced as specified by the period parameter.
569      * <P>
570      * Note that once the timer notification has been added into the list of notifications,
571      * its associated date, period and number of occurrences cannot be updated.
572      * <P>
573      * In the case of a periodic notification, uses a <i>fixed-delay</i> execution scheme, as specified in
574      * {@link java.util.Timer}. In order to use a <i>fixed-rate</i> execution scheme, use
575      * {@link #addNotification(String, String, Object, Date, long, long, boolean)} instead.
576      *
577      * @param type The timer notification type.
578      * @param message The timer notification detailed message.
579      * @param userData The timer notification user data object.
580      * @param date The date when the notification occurs.
581      * @param period The period of the timer notification (in milliseconds).
582      * @param nbOccurences The total number the timer notification will be emitted.
583      *
584      * @return The identifier of the new created timer notification.
585      *
586      * @exception java.lang.IllegalArgumentException The period or the number of occurrences is negative
587      *
588      * @see #addNotification(String, String, Object, Date, long, long, boolean)
589      */

590 // NPCTE fix for bugId 4464388, esc 0, MR , to be added after modification of jmx spec
591
// public synchronized Integer addNotification(String type, String message, Serializable userData,
592
// Date date, long period)
593
// end of NPCTE fix for bugId 4464388 */
594

595     public synchronized Integer JavaDoc addNotification(String JavaDoc type, String JavaDoc message, Object JavaDoc userData,
596                                                 Date JavaDoc date, long period, long nbOccurences)
597         throws java.lang.IllegalArgumentException JavaDoc {
598         
599       return addNotification(type, message, userData, date, period, nbOccurences, false);
600     }
601         
602     /**
603      * Creates a new timer notification with the specified <CODE>type</CODE>, <CODE>message</CODE>
604      * and <CODE>userData</CODE> and inserts it into the list of notifications with a given date
605      * and period and a null number of occurrences.
606      * <P>
607      * The timer notification will repeat continuously using the timer period using a <i>fixed-delay</i>
608      * execution scheme, as specified in {@link java.util.Timer}. In order to use a <i>fixed-rate</i>
609      * execution scheme, use {@link #addNotification(String, String, Object, Date, long, long,
610      * boolean)} instead.
611      * <P>
612      * If the timer notification to be inserted has a date that is before the current date,
613      * the method behaves as if the specified date were the current date. The
614      * first notification is delivered immediately and the subsequent ones are
615      * spaced as specified by the period parameter.
616      *
617      * @param type The timer notification type.
618      * @param message The timer notification detailed message.
619      * @param userData The timer notification user data object.
620      * @param date The date when the notification occurs.
621      * @param period The period of the timer notification (in milliseconds).
622      *
623      * @return The identifier of the new created timer notification.
624      *
625      * @exception java.lang.IllegalArgumentException The period is negative or
626      * the date notification is before the current date.
627      */

628 // NPCTE fix for bugId 4464388, esc 0, MR , to be added after modification of jmx spec
629
// public synchronized Integer addNotification(String type, String message, Serializable userData,
630
// Date date, long period)
631
// end of NPCTE fix for bugId 4464388 */
632

633     public synchronized Integer JavaDoc addNotification(String JavaDoc type, String JavaDoc message, Object JavaDoc userData,
634                                                 Date JavaDoc date, long period)
635         throws java.lang.IllegalArgumentException JavaDoc {
636         
637         return (addNotification(type, message, userData, date, period, 0));
638     }
639   
640     /**
641      * Creates a new timer notification with the specified <CODE>type</CODE>, <CODE>message</CODE>
642      * and <CODE>userData</CODE> and inserts it into the list of notifications with a given date
643      * and a null period and number of occurrences.
644      * <P>
645      * The timer notification will be handled once at the specified date.
646      * <P>
647      * If the timer notification to be inserted has a date that is before the current date,
648      * the method behaves as if the specified date were the current date and the
649      * notification is delivered immediately.
650      *
651      * @param type The timer notification type.
652      * @param message The timer notification detailed message.
653      * @param userData The timer notification user data object.
654      * @param date The date when the notification occurs.
655      *
656      * @return The identifier of the new created timer notification.
657      *
658      * @exception java.lang.IllegalArgumentException The date notification is before the current date.
659      */

660 // NPCTE fix for bugId 4464388, esc 0, MR, to be added after modification of jmx spec
661
// public synchronized Integer addNotification(String type, String message, Serializable userData, Date date)
662
// throws java.lang.IllegalArgumentException {
663
// end of NPCTE fix for bugId 4464388
664

665     public synchronized Integer JavaDoc addNotification(String JavaDoc type, String JavaDoc message, Object JavaDoc userData, Date JavaDoc date)
666         throws java.lang.IllegalArgumentException JavaDoc {
667
668         
669         return (addNotification(type, message, userData, date, 0, 0));
670     }
671   
672     /**
673      * Removes the timer notification corresponding to the specified identifier from the list of notifications.
674      *
675      * @param id The timer notification identifier.
676      *
677      * @exception InstanceNotFoundException The specified identifier does not correspond to any timer notification
678      * in the list of notifications of this timer MBean.
679      */

680     public synchronized void removeNotification(Integer JavaDoc id) throws InstanceNotFoundException JavaDoc {
681   
682         // Check that the notification to remove is effectively in the timer table.
683
//
684
if (timerTable.containsKey(id) == false) {
685             throw new InstanceNotFoundException JavaDoc("Timer notification to remove not in the list of notifications");
686         }
687                 
688         // Stop the TimerAlarmClock.
689
//
690
Object JavaDoc[] obj = (Object JavaDoc[])timerTable.get(id);
691         TimerAlarmClock JavaDoc alarmClock = (TimerAlarmClock JavaDoc)obj[ALARM_CLOCK_INDEX];
692         if (alarmClock != null) {
693 // alarmClock.interrupt();
694
// try {
695
// // Wait until the thread die.
696
// //
697
// alarmClock.join();
698
// } catch (InterruptedException e) {
699
// // Ignore...
700
// }
701
// // Remove the reference on the TimerAlarmClock.
702
// //
703
alarmClock.cancel();
704             alarmClock = null;
705         }
706         
707         // Remove the timer notification from the timer table.
708
//
709
if (isTraceOn()) {
710             trace("removeNotification", "removing timer notification:" +
711                   "\n\tNotification source = " + ((TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX]).getSource() +
712                   "\n\tNotification type = " + ((TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX]).getType() +
713                   "\n\tNotification ID = " + ((TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX]).getNotificationID() +
714                   "\n\tNotification date = " + obj[TIMER_DATE_INDEX] +
715                   "\n\tNotification period = " + obj[TIMER_PERIOD_INDEX] +
716                   "\n\tNotification nb of occurrences = " + obj[TIMER_NB_OCCUR_INDEX] +
717                   "\n\tNotification executes at fixed rate = " + obj[FIXED_RATE_INDEX]);
718         }
719         
720         timerTable.remove(id);
721         
722         if (isTraceOn()) {
723             trace("removeNotification", "timer notification removed");
724         }
725     }
726   
727     /**
728      * Removes all the timer notifications corresponding to the specified type from the list of notifications.
729      *
730      * @param type The timer notification type.
731      *
732      * @exception InstanceNotFoundException The specified type does not correspond to any timer notification
733      * in the list of notifications of this timer MBean.
734      */

735     public synchronized void removeNotifications(String JavaDoc type) throws InstanceNotFoundException JavaDoc {
736         
737         TimerNotification JavaDoc notif;
738         Integer JavaDoc id;
739     TimerAlarmClock JavaDoc alarmClock;
740     Object JavaDoc[] obj;
741         
742         Vector JavaDoc v = getNotificationIDs(type);
743         
744         // Check that the notification to remove is effectively in the timer table.
745
//
746
if (v.isEmpty()) {
747             throw new InstanceNotFoundException JavaDoc("Timer notifications to remove not in the list of notifications");
748         }
749         
750         Enumeration JavaDoc e = v.elements();
751         while (e.hasMoreElements()) {
752             notif = (TimerNotification JavaDoc)e.nextElement();
753             id = notif.getNotificationID();
754         obj = (Object JavaDoc[])timerTable.get(id);
755
756             timerTable.remove(id);
757
758         alarmClock = (TimerAlarmClock JavaDoc)obj[ALARM_CLOCK_INDEX];
759         if (alarmClock != null) {
760         alarmClock.cancel();
761         }
762         }
763     }
764             
765     /**
766      * Removes all the timer notifications from the list of notifications
767      * and resets the counter used to update the timer notification identifiers.
768      */

769     public synchronized void removeAllNotifications() {
770         
771         Object JavaDoc[] obj;
772         TimerAlarmClock JavaDoc alarmClock;
773
774     Enumeration JavaDoc e = timerTable.elements();
775         while (e.hasMoreElements()) {
776           
777             obj = (Object JavaDoc[])e.nextElement();
778           
779             // Stop the TimerAlarmClock.
780
//
781
alarmClock = (TimerAlarmClock JavaDoc)obj[ALARM_CLOCK_INDEX];
782 // if (alarmClock != null) {
783
// alarmClock.interrupt();
784
// try {
785
// // Wait until the thread die.
786
// //
787
// alarmClock.join();
788
// } catch (InterruptedException ex) {
789
// // Ignore...
790
// }
791
// Remove the reference on the TimerAlarmClock.
792
//
793
// }
794
alarmClock.cancel();
795             alarmClock = null;
796         }
797                 
798         // Remove all the timer notifications from the timer table.
799
//
800
if (isTraceOn()) {
801             trace("removeAllNotifications", "removing all timer notifications");
802         }
803         
804         timerTable.clear();
805         
806         if (isTraceOn()) {
807             trace("removeAllNotifications", "all timer notifications removed");
808         }
809         
810         // Reset the counterID.
811
//
812
counterID = 0;
813         
814         if (isTraceOn()) {
815             trace("removeAllNotifications", "timer notification counter ID resetted");
816         }
817     }
818     
819     // GETTERS AND SETTERS
820
//--------------------
821

822     /**
823      * Gets the number of timer notifications registered into the list of notifications.
824      *
825      * @return The number of timer notifications.
826      */

827     public int getNbNotifications() {
828         return timerTable.size();
829     }
830     
831     /**
832      * Gets all timer notification identifiers registered into the list of notifications.
833      *
834      * @return A vector of <CODE>Integer</CODE> objects containing all the timer notification identifiers.
835      * <BR>The vector is empty if there is no timer notification registered for this timer MBean.
836      */

837     public synchronized Vector JavaDoc getAllNotificationIDs() {
838         
839         Vector JavaDoc v = new Vector JavaDoc();
840         
841         Enumeration JavaDoc e = timerTable.keys();
842         while (e.hasMoreElements()) {
843           
844             v.addElement((Integer JavaDoc)e.nextElement());
845         }
846         return v;
847     }
848     
849     /**
850      * Gets all the identifiers of timer notifications corresponding to the specified type.
851      *
852      * @param type The timer notification type.
853      *
854      * @return A vector of <CODE>Integer</CODE> objects containing all the identifiers of
855      * timer notifications with the specified <CODE>type</CODE>.
856      * <BR>The vector is empty if there is no timer notifications registered for this timer MBean
857      * with the specified <CODE>type</CODE>.
858      */

859     public synchronized Vector JavaDoc getNotificationIDs(String JavaDoc type) {
860         
861         Object JavaDoc[] obj;
862         String JavaDoc s;
863         
864         Vector JavaDoc v = new Vector JavaDoc();
865         
866         Enumeration JavaDoc e = timerTable.elements();
867         
868         // If the specified type is null, retreive all the timer notificatiosn which type is null.
869
//
870
if (type == null) {
871             while (e.hasMoreElements()) {
872                 obj = (Object JavaDoc[])e.nextElement();
873                 s = ((TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX]).getType();
874             
875                 if (s == null) {
876                     v.addElement((TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX]);
877                 }
878             }
879         }
880         else {
881             while (e.hasMoreElements()) {
882                 obj = (Object JavaDoc[])e.nextElement();
883                 s = ((TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX]).getType();
884             
885                 if (type.equals(s)) {
886                     v.addElement((TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX]);
887                 }
888             }
889         }
890         return v;
891     }
892     
893     /**
894      * Gets the timer notification type corresponding to the specified identifier.
895      *
896      * @param id The timer notification identifier.
897      *
898      * @return The timer notification type or null if the identifier is not mapped to any
899      * timer notification registered for this timer MBean.
900      */

901     public String JavaDoc getNotificationType(Integer JavaDoc id) {
902         
903         Object JavaDoc[] obj = (Object JavaDoc[])timerTable.get(id);
904         if (obj != null) {
905             return ( (String JavaDoc)((TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX]).getType() );
906         }
907         return null;
908     }
909     
910     /**
911      * Gets the timer notification detailed message corresponding to the specified identifier.
912      *
913      * @param id The timer notification identifier.
914      *
915      * @return The timer notification detailed message or null if the identifier is not mapped to any
916      * timer notification registered for this timer MBean.
917      */

918     public String JavaDoc getNotificationMessage(Integer JavaDoc id) {
919         
920         Object JavaDoc[] obj = (Object JavaDoc[])timerTable.get(id);
921         if (obj != null) {
922             return ( (String JavaDoc)((TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX]).getMessage() );
923         }
924         return null;
925     }
926     
927     /**
928      * Gets the timer notification user data object corresponding to the specified identifier.
929      *
930      * @param id The timer notification identifier.
931      *
932      * @return The timer notification user data object or null if the identifier is not mapped to any
933      * timer notification registered for this timer MBean.
934      */

935     // NPCTE fix for bugId 4464388, esc 0, MR, 03 sept 2001, to be added after modification of jmx spec
936
//public Serializable getNotificationUserData(Integer id) {
937
// end of NPCTE fix for bugId 4464388
938

939     public Object JavaDoc getNotificationUserData(Integer JavaDoc id) {
940         Object JavaDoc[] obj = (Object JavaDoc[])timerTable.get(id);
941         if (obj != null) {
942             return ( ((TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX]).getUserData() );
943         }
944         return null;
945     }
946     
947     /**
948      * Gets a copy of the date associated to a timer notification.
949      *
950      * @param id The timer notification identifier.
951      *
952      * @return A copy of the date or null if the identifier is not mapped to any
953      * timer notification registered for this timer MBean.
954      */

955     public Date JavaDoc getDate(Integer JavaDoc id) {
956         
957         Object JavaDoc[] obj = (Object JavaDoc[])timerTable.get(id);
958         if (obj != null) {
959             Date JavaDoc date = (Date JavaDoc)obj[TIMER_DATE_INDEX];
960             return (new Date JavaDoc(date.getTime()));
961         }
962         return null;
963     }
964   
965     /**
966      * Gets a copy of the period (in milliseconds) associated to a timer notification.
967      *
968      * @param id The timer notification identifier.
969      *
970      * @return A copy of the period or null if the identifier is not mapped to any
971      * timer notification registered for this timer MBean.
972      */

973     public Long JavaDoc getPeriod(Integer JavaDoc id) {
974         
975         Object JavaDoc[] obj = (Object JavaDoc[])timerTable.get(id);
976         if (obj != null) {
977             Long JavaDoc period = (Long JavaDoc)obj[TIMER_PERIOD_INDEX];
978             return (new Long JavaDoc(period.longValue()));
979         }
980         return null;
981     }
982   
983     /**
984      * Gets a copy of the remaining number of occurrences associated to a timer notification.
985      *
986      * @param id The timer notification identifier.
987      *
988      * @return A copy of the remaining number of occurrences or null if the identifier is not mapped to any
989      * timer notification registered for this timer MBean.
990      */

991     public Long JavaDoc getNbOccurences(Integer JavaDoc id) {
992         
993         Object JavaDoc[] obj = (Object JavaDoc[])timerTable.get(id);
994         if (obj != null) {
995             Long JavaDoc nbOccurences = (Long JavaDoc)obj[TIMER_NB_OCCUR_INDEX];
996             return (new Long JavaDoc(nbOccurences.longValue()));
997         }
998         return null;
999     }
1000    
1001    /**
1002     * Gets a copy of the flag indicating whether a periodic notification is
1003     * executed at <i>fixed-delay</i> or at <i>fixed-rate</i>.
1004     *
1005     * @param id The timer notification identifier.
1006     *
1007     * @return A copy of the flag indicating whether a periodic notification is
1008     * executed at <i>fixed-delay</i> or at <i>fixed-rate</i>.
1009     */

1010    public Boolean JavaDoc getFixedRate(Integer JavaDoc id) {
1011
1012      Object JavaDoc[] obj = (Object JavaDoc[])timerTable.get(id);
1013      if (obj != null) {
1014        Boolean JavaDoc fixedRate = (Boolean JavaDoc)obj[FIXED_RATE_INDEX];
1015        return (new Boolean JavaDoc(fixedRate.booleanValue()));
1016      }
1017      return null;
1018    }
1019
1020    /**
1021     * Gets the flag indicating whether or not the timer sends past notifications.
1022     * <BR>The default value of the past notifications sending on/off flag is <CODE>false</CODE>.
1023     *
1024     * @return The past notifications sending on/off flag value.
1025     *
1026     * @see #setSendPastNotifications
1027     */

1028    public boolean getSendPastNotifications() {
1029        return sendPastNotifications;
1030    }
1031  
1032    /**
1033     * Sets the flag indicating whether the timer sends past notifications or not.
1034     * <BR>The default value of the past notifications sending on/off flag is <CODE>false</CODE>.
1035     *
1036     * @param value The past notifications sending on/off flag value.
1037     *
1038     * @see #getSendPastNotifications
1039     */

1040    public void setSendPastNotifications(boolean value) {
1041        sendPastNotifications = value;
1042    }
1043    
1044    /**
1045     * Tests whether the timer MBean is active.
1046     * A timer MBean is marked active when the {@link #start start} method is called.
1047     * It becomes inactive when the {@link #stop stop} method is called.
1048     * <BR>The default value of the active on/off flag is <CODE>false</CODE>.
1049     *
1050     * @return <CODE>true</CODE> if the timer MBean is active, <CODE>false</CODE> otherwise.
1051     */

1052    public boolean isActive() {
1053        return isActive;
1054    }
1055    
1056    /**
1057     * Tests whether the list of timer notifications is empty.
1058     *
1059     * @return <CODE>true</CODE> if the list of timer notifications is empty, <CODE>false</CODE> otherwise.
1060     */

1061    public boolean isEmpty() {
1062        return (timerTable.isEmpty());
1063    }
1064    
1065    /*
1066     * ------------------------------------------
1067     * PRIVATE METHODS
1068     * ------------------------------------------
1069     */

1070        
1071    /**
1072     * Sends or not past notifications depending on the specified flag.
1073     *
1074     * @param currentDate The current date.
1075     * @param currentFlag The flag indicating if past notifications must be sent or not.
1076     */

1077    private synchronized void sendPastNotifications(Date JavaDoc currentDate, boolean currentFlag) {
1078        
1079        TimerNotification JavaDoc notif;
1080        Integer JavaDoc notifID;
1081        Date JavaDoc date;
1082        Object JavaDoc[] obj;
1083        
1084        Enumeration JavaDoc e = timerTable.elements();
1085        while (e.hasMoreElements()) {
1086          
1087            obj = (Object JavaDoc[])e.nextElement();
1088          
1089            // Retrieve the timer notification and the date notification.
1090
//
1091
notif = (TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX];
1092            notifID = notif.getNotificationID();
1093            date = (Date JavaDoc)obj[TIMER_DATE_INDEX];
1094                  
1095            // Update the timer notification while:
1096
// - the timer notification date is earlier than the current date
1097
// - the timer notification has not been removed from the timer table.
1098
//
1099
while ( (currentDate.after(date)) && (timerTable.containsKey(notifID)) ) {
1100                                
1101                if (currentFlag == true) {
1102                    if (isTraceOn()) {
1103                        trace("sendPastNotifications", "sending past timer notification:" +
1104                              "\n\tNotification source = " + notif.getSource() +
1105                              "\n\tNotification type = " + notif.getType() +
1106                              "\n\tNotification ID = " + notif.getNotificationID() +
1107                              "\n\tNotification date = " + date +
1108                              "\n\tNotification period = " + obj[TIMER_PERIOD_INDEX] +
1109                              "\n\tNotification nb of occurrences = " + obj[TIMER_NB_OCCUR_INDEX] +
1110                              "\n\tNotification executes at fixed rate = " + obj[FIXED_RATE_INDEX]);
1111                    }
1112                    sendNotification(date, notif);
1113                    
1114                    if (isTraceOn()) {
1115                        trace("sendPastNotifications", "past timer notification sent");
1116                    }
1117                }
1118                
1119                // Update the date and the number of occurrences of the timer notification.
1120
//
1121
updateTimerTable(notif.getNotificationID());
1122            }
1123        }
1124    }
1125         
1126    /**
1127     * If the timer notification is not periodic, it is removed from the list of notifications.
1128     * <P>
1129     * If the timer period of the timer notification has a non null periodicity,
1130     * the date of the timer notification is updated by adding the periodicity.
1131     * The associated TimerAlarmClock is updated by setting its timeout to the period value.
1132     * <P>
1133     * If the timer period has a defined number of occurrences, the timer
1134     * notification is updated if the number of occurrences has not yet been reached.
1135     * Otherwise it is removed from the list of notifications.
1136     *
1137     * @param notifID The timer notification identifier to update.
1138     */

1139    private synchronized void updateTimerTable(Integer JavaDoc notifID) {
1140        
1141        // Retrieve the timer notification and the TimerAlarmClock.
1142
//
1143
Object JavaDoc[] obj = (Object JavaDoc[])timerTable.get(notifID);
1144        Date JavaDoc date = (Date JavaDoc)obj[TIMER_DATE_INDEX];
1145        Long JavaDoc period = (Long JavaDoc)obj[TIMER_PERIOD_INDEX];
1146        Long JavaDoc nbOccurences = (Long JavaDoc)obj[TIMER_NB_OCCUR_INDEX];
1147        Boolean JavaDoc fixedRate = (Boolean JavaDoc)obj[FIXED_RATE_INDEX];
1148        TimerAlarmClock JavaDoc alarmClock = (TimerAlarmClock JavaDoc)obj[ALARM_CLOCK_INDEX];
1149        
1150        if (period.longValue() != 0) {
1151          
1152            // Update the date and the number of occurrences of the timer notification
1153
// and the TimerAlarmClock time out.
1154
// NOTES :
1155
// nbOccurences = 0 notifies an infinite periodicity.
1156
// nbOccurences = 1 notifies a finite periodicity that has reached its end.
1157
// nbOccurences > 1 notifies a finite periodicity that has not yet reached its end.
1158
//
1159
if ((nbOccurences.longValue() == 0) || (nbOccurences.longValue() > 1)) {
1160                
1161                date.setTime(date.getTime() + period.longValue());
1162                obj[TIMER_NB_OCCUR_INDEX] = new Long JavaDoc(java.lang.Math.max(0L, (nbOccurences.longValue() - 1)));
1163                nbOccurences = (Long JavaDoc)obj[TIMER_NB_OCCUR_INDEX];
1164                                
1165                if (isActive == true) {
1166                  if (fixedRate.booleanValue())
1167                  {
1168                    alarmClock = new TimerAlarmClock JavaDoc(this, date);
1169                    obj[ALARM_CLOCK_INDEX] = (Object JavaDoc)alarmClock;
1170            timer.schedule(alarmClock, alarmClock.next);
1171                  }
1172                  else
1173                  {
1174                    alarmClock = new TimerAlarmClock JavaDoc(this, period.longValue());
1175                    obj[ALARM_CLOCK_INDEX] = (Object JavaDoc)alarmClock;
1176            timer.schedule(alarmClock, alarmClock.timeout);
1177                  }
1178                }
1179                if (isTraceOn()) {
1180                    TimerNotification JavaDoc notif = (TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX];
1181                    trace("updateTimerTable", "update timer notification with:" +
1182                          "\n\tNotification source = " + notif.getSource() +
1183                          "\n\tNotification type = " + notif.getType() +
1184                          "\n\tNotification ID = " + notifID +
1185                          "\n\tNotification date = " + date +
1186                          "\n\tNotification period = " + period +
1187                          "\n\tNotification nb of occurrences = " + nbOccurences +
1188                          "\n\tNotification executes at fixed rate = " + fixedRate);
1189                }
1190            }
1191            else {
1192                if (alarmClock != null) {
1193// alarmClock.interrupt();
1194
// try {
1195
// // Wait until the thread die.
1196
// //
1197
// alarmClock.join();
1198
// } catch (InterruptedException e) {
1199
// // Ignore...
1200
// }
1201
alarmClock.cancel();
1202                    // Remove the reference on the TimerAlarmClock.
1203
//
1204
alarmClock = null;
1205                }
1206                timerTable.remove(notifID);
1207            }
1208        }
1209        else {
1210            if (alarmClock != null) {
1211// alarmClock.interrupt();
1212
// try {
1213
// // Wait until the thread die.
1214
// //
1215
// alarmClock.join();
1216
// } catch (InterruptedException e) {
1217
// // Ignore...
1218
// }
1219

1220           alarmClock.cancel();
1221
1222                // Remove the reference on the TimerAlarmClock.
1223
//
1224
alarmClock = null;
1225            }
1226            timerTable.remove(notifID);
1227        }
1228    }
1229    
1230    /*
1231     * ------------------------------------------
1232     * PACKAGE METHODS
1233     * ------------------------------------------
1234     */

1235    
1236    /**
1237     * This method is called by the timer each time
1238     * the TimerAlarmClock has exceeded its timeout.
1239     *
1240     * @param notification The TimerAlarmClock notification.
1241     */

1242    void notifyAlarmClock(TimerAlarmClockNotification JavaDoc notification) {
1243                
1244        Object JavaDoc[] obj;
1245        TimerNotification JavaDoc timerNotification = null;
1246        Date JavaDoc timerDate = null;
1247        
1248        // Retrieve the timer notification associated to the alarm-clock.
1249
//
1250
TimerAlarmClock JavaDoc alarmClock = (TimerAlarmClock JavaDoc)notification.getSource();
1251        
1252        Enumeration JavaDoc e = timerTable.elements();
1253        while (e.hasMoreElements()) {
1254            obj = (Object JavaDoc[])e.nextElement();
1255            if (obj[ALARM_CLOCK_INDEX] == alarmClock) {
1256                timerNotification = (TimerNotification JavaDoc)obj[TIMER_NOTIF_INDEX];
1257                timerDate = (Date JavaDoc)obj[TIMER_DATE_INDEX];
1258                break;
1259            }
1260        }
1261        
1262        // Notify the timer.
1263
//
1264
sendNotification(timerDate, timerNotification);
1265        
1266        // Update the notification and the TimerAlarmClock timeout.
1267
//
1268
updateTimerTable(timerNotification.getNotificationID());
1269    }
1270
1271    /**
1272     * This method is used by the timer MBean to update and send a timer
1273     * notification to all the listeners registered for this kind of notification.
1274     *
1275     * @param timeStamp The notification emission date.
1276     * @param notification The timer notification to send.
1277     */

1278    void sendNotification(Date JavaDoc timeStamp, TimerNotification JavaDoc notification) {
1279                
1280        if (isTraceOn()) {
1281            trace("sendNotification", "sending timer notification:" +
1282                  "\n\tNotification source = " + notification.getSource() +
1283                  "\n\tNotification type = " + notification.getType() +
1284                  "\n\tNotification ID = " + notification.getNotificationID() +
1285                  "\n\tNotification date = " + timeStamp);
1286        }
1287        long curSeqNumber;
1288        synchronized(this) {
1289            sequenceNumber = sequenceNumber + 1;
1290        curSeqNumber = sequenceNumber;
1291        }
1292        synchronized (notification) {
1293            notification.setTimeStamp(timeStamp.getTime());
1294            notification.setSequenceNumber(curSeqNumber);
1295            this.sendNotification((TimerNotification JavaDoc)notification.cloneTimerNotification());
1296        }
1297        
1298        if (isTraceOn()) {
1299            trace("sendNotification", "timer notification sent");
1300        }
1301    }
1302}
1303
1304/**
1305 * TimerAlarmClock inner class:
1306 * This class provides a simple implementation of an alarm clock MBean.
1307 * The aim of this MBean is to set up an alarm which wakes up the timer every timeout (fixed-delay)
1308 * or at the specified date (fixed-rate).
1309 */

1310
1311class TimerAlarmClock extends java.util.TimerTask JavaDoc {
1312
1313    Timer JavaDoc listener = null;
1314    long timeout = 10000;
1315    Date JavaDoc next = null;
1316    
1317    /*
1318     * ------------------------------------------
1319     * CONSTRUCTORS
1320     * ------------------------------------------
1321     */

1322    
1323    public TimerAlarmClock(Timer JavaDoc listener, long timeout) {
1324        this.listener = listener;
1325        this.timeout = Math.max(0L, timeout);
1326    }
1327
1328    public TimerAlarmClock(Timer JavaDoc listener, Date JavaDoc next) {
1329        this.listener = listener;
1330        this.next = next;
1331    }
1332
1333    /*
1334     * ------------------------------------------
1335     * PUBLIC METHODS
1336     * ------------------------------------------
1337     */

1338
1339    /**
1340     * This method is called by the timer when it is started.
1341     */

1342    public void run() {
1343        
1344        try {
1345            //this.sleep(timeout);
1346
TimerAlarmClockNotification JavaDoc notif = new TimerAlarmClockNotification JavaDoc(this);
1347            listener.notifyAlarmClock(notif);
1348        } catch (Exception JavaDoc e) {
1349        if (Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_TIMER)) {
1350            Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_TIMER, "TimerAlarmClock", "run", "Got an exception when sending a notifiacation: "+e);
1351        }
1352        }
1353    }
1354}
1355
Popular Tags