001: /**
002: * The XMOJO Project 5
003: * Copyright © 2003 XMOJO.org. All rights reserved.
004:
005: * NO WARRANTY
006:
007: * BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
008: * THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
009: * OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
010: * PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
011: * OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
012: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
013: * TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE
014: * LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
015: * REPAIR OR CORRECTION.
016:
017: * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
018: * ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
019: * THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
020: * GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
021: * USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF
022: * DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
023: * PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE),
024: * EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
025: * SUCH DAMAGES.
026: **/package javax.management.timer;
027:
028: import java.io.Serializable;
029: import java.util.Date;
030: import java.util.Enumeration;
031: import java.util.Hashtable;
032: import java.util.Vector;
033:
034: import javax.management.ObjectName;
035: import javax.management.MBeanRegistration;
036: import javax.management.MBeanServer;
037: import javax.management.NotificationBroadcasterSupport;
038: import javax.management.InstanceNotFoundException;
039:
040: //import com.adventnet.agent.utilities.scheduler.Scheduler;
041:
042: import com.adventnet.agent.logging.Log;
043: import com.adventnet.agent.logging.LogFactory;
044:
045: /**
046: * This class provides the implementation of the timer MBean. The timer MBean
047: * sends out an alarm at a specified time that wakes up all the listeners
048: * registered to receive timer notifications.
049: * <P>
050: * This class manages a list of dated timer notifications. A method allows
051: * users to add/remove as many notifications as required. When a timer
052: * notification is emitted by the timer and becomes obsolete, it is
053: * automatically removed from the list of timer notifications.
054: * <BR>Additional timer notifications can be added into regularly repeating
055: * notifications.
056: * <P>
057: *
058: * Note:
059: * <OL>
060: * <LI>All notifications before the time when the <CODE>addNotification</CODE>
061: * method is called are ignored, irrespective of the
062: * <CODE>sendPastNotifications</CODE> flag.
063: * <LI>When sending timer notifications, the timer updates the notification
064: * sequence number irrespective of the notification type.
065: * <LI>The timer service relies on the system date of the host where the
066: * <CODE>Timer</CODE> class is loaded. Callers may be unable to add
067: * notifications to the timer, and listeners may recieve untimely notifications
068: * if their host has a different system date. To avoid such problems,
069: * synchronize the system date of all host machines where timing is needed.
070: * </OL>
071: */
072: public class Timer extends NotificationBroadcasterSupport implements
073: TimerMBean, MBeanRegistration, Serializable {
074: /**
075: * Number of milliseconds in one second.
076: * This constant can be used in addNotification method.
077: */
078: public static final long ONE_SECOND = 1000;
079:
080: /**
081: * Number of milliseconds in one minute.
082: * This constant can be used in addNotification method.
083: */
084: public static final long ONE_MINUTE = 60 * ONE_SECOND;
085:
086: /**
087: * Number of milliseconds in one hour.
088: * This constant can be used in addNotification method.
089: */
090: public static final long ONE_HOUR = 60 * ONE_MINUTE;
091:
092: /**
093: * Number of milliseconds in one day.
094: * This constant can be used in addNotification method.
095: */
096: public static final long ONE_DAY = 24 * ONE_HOUR;
097:
098: /**
099: * Number of milliseconds in one week.
100: * This constant can be used in addNotification method.
101: */
102: public static final long ONE_WEEK = 7 * ONE_DAY;
103:
104: /**
105: * Scheduler that will be used to schedule the TimerNotifications.
106: */
107: private Scheduler scheduler = null;
108:
109: /**
110: * Variable representing the unique Notification ID.
111: */
112: private int notificationID = 0;
113:
114: /**
115: * Hashtable where the Timer Tasks are stored.
116: */
117: private Hashtable timerTable = new Hashtable();
118:
119: /**
120: * Boolean to indicate if pastNotifications flag is enabled or not.
121: * This attribute is used to specify if the timer has to send past
122: * notifications after start.
123: * <BR>The default value is set to <CODE>false</CODE>.
124: */
125: private boolean sendPastNotifications = false;
126:
127: /**
128: * Variable to store the ObjectName of the Timer.
129: */
130: private ObjectName objectName = null;
131:
132: /**
133: * Variable indicating the state of the Timer.
134: */
135: private boolean active = false;
136:
137: /**
138: * The Logger instance used for Logging purposes.
139: */
140: private Log log = null;
141:
142: // the following are present here to make serialization compatible with RI
143:
144: /**
145: * The notification counter ID.
146: * Used to keep the max key value inserted into the timer table.
147: */
148: private int counterID = 0;
149:
150: // not used
151: private String dbgTag = "";
152:
153: // end of dummy variables for serialization compatible
154:
155: /**
156: * Default Constructor
157: */
158: public Timer() {
159: try {
160: log = LogFactory.getInstance("JMX");
161: } catch (Exception e) {
162: e.printStackTrace();
163: }
164:
165: log.trace("Timer Instantiated");
166: }
167:
168: // Mbean Registration methods
169:
170: /**
171: * Allows the timer MBean to perform any operations it needs before
172: * being registered in the MBean server.
173: *
174: * @param server The MBean server in which the timer MBean will be registered.
175: *
176: * @param name The object name of the timer MBean.
177: *
178: * @return The name of the timer MBean registered.
179: *
180: * @exception java.lang.Exception
181: */
182: public ObjectName preRegister(MBeanServer server,
183: ObjectName objectName) throws Exception {
184: this .objectName = ((objectName == null) ? new ObjectName(
185: "Services", "type", "Timer") : objectName);
186: if (scheduler == null)
187: scheduler = Scheduler.createScheduler(this .objectName
188: .toString(), 2);
189:
190: return this .objectName;
191: }
192:
193: /**
194: * Allows the timer MBean to perform any operations needed after having been
195: * registered in the MBean server or after the registration has failed.
196: * <P>
197: * Not used in this context.
198: */
199: public void postRegister(Boolean registrationDone) {
200: }
201:
202: /**
203: * Allows the timer MBean to perform any operations it needs before
204: * being de-registered by the MBean server.
205: * <P>
206: * Stops the timer.
207: *
208: * @exception java.lang.Exception
209: */
210: public void preDeregister() throws java.lang.Exception {
211: stop();
212: }
213:
214: /**
215: * Allows the timer MBean to perform any operations needed after having been
216: * de-registered by the MBean server.
217: */
218: public void postDeregister() {
219: if (scheduler != null) {
220: scheduler.deregisterThisScheduler("TIMER");
221: }
222: }
223:
224: /**
225: * This method starts the timer.
226: * <P>
227: * If there is one or more timer notifications before the time in the
228: * list of notifications, the notification is sent according to the
229: * <CODE>sendPastNotifications</CODE> flag and then, updated according
230: * to its period and remaining number of occurences. If the timer
231: * notification date remains earlier than the current date, this
232: * notification is just removed from the list of notifications.
233: */
234: public synchronized void start() {
235: try {
236: if (objectName == null)
237: objectName = new ObjectName("Services", "type", "Timer");
238: } catch (Exception e) {
239: }
240:
241: if (scheduler == null) {
242: scheduler = Scheduler.createScheduler(this .objectName
243: .toString(), 2);
244: Enumeration e = timerTable.keys();
245:
246: while (e.hasMoreElements()) {
247: Task t = (Task) (timerTable.get(e.nextElement()));
248: scheduler.scheduleTask(t, new Date(t
249: .getTimerNotification().getTimeStamp()));
250: }
251: }
252:
253: sendExpiredNotifications(sendPastNotifications);
254:
255: if (active == false || !scheduler.isAlive()) {
256: scheduler.start();
257:
258: //printing the values ...
259: Enumeration e = timerTable.keys();
260: while (e.hasMoreElements()) {
261: Task t = (Task) (timerTable.get(e.nextElement()));
262: }
263:
264: active = true;
265: return;
266: }
267: }
268:
269: /**
270: * This method stops the timer.
271: */
272: public synchronized void stop() {
273: scheduler.killScheduler();
274: scheduler.cleanUp();
275: scheduler = null;
276:
277: active = false;
278: }
279:
280: /**
281: * This method creates a new timer notification with the specified
282: * <CODE>type</CODE>, <CODE>message</CODE> and <CODE>userData</CODE>
283: * and inserts it into the list of notifications with a given date and
284: * a null period and number of occurences.
285: * <P>
286: * The timer notification will be handled once at the specified date.
287: *
288: * @param type The timer notification type.
289: *
290: * @param message The timer notification detailed message.
291: *
292: * @param userData The timer notification user data object.
293: *
294: * @param date The date when the notification occurs.
295: *
296: * @return An instance of java.lang.Integer which is the identifier of
297: * the new created timer notification.
298: *
299: * @exception java.lang.IllegalArgumentException The date notification
300: * is before the current date.
301: */
302: public Integer addNotification(String type, String message,
303: Object userData, Date date) throws IllegalArgumentException {
304: log
305: .trace("addNotificaation Called with 0 period and 0 occurences");
306: return addNotification(type, message, userData, date, 0, 1);
307: }
308:
309: /**
310: * This method creates a new timer notification with the specified
311: * <CODE>type</CODE>, <CODE>message</CODE> and <CODE>userData</CODE>
312: * and inserts it into the list of notifications with a given date
313: * and period and a null number of occurences.
314: * <P>
315: * The timer notification will repeat continuously using the timer period.
316: *
317: * @param type The timer notification type.
318: *
319: * @param message The timer notification detailed message.
320: *
321: * @param userData The timer notification user data object.
322: *
323: * @param date The date when the notification occurs.
324: *
325: * @param period The period of the timer notification (in milliseconds).
326: *
327: * @return An instance of java.lang.Integer which is the identifier of
328: * the new created timer notification.
329: *
330: * @exception java.lang.IllegalArgumentException - The period is negative
331: * or the date notification is before the current date.
332: */
333: public Integer addNotification(String type, String message,
334: Object userData, Date date, long period)
335: throws IllegalArgumentException {
336: log.trace("addNotification called with 0 occurences");
337: return addNotification(type, message, userData, date, period, 0);
338: }
339:
340: /**
341: * This method creates a new timer notification with the specified
342: * <CODE>type</CODE>, <CODE>message</CODE> and <CODE>userData</CODE> and
343: * inserts it into the list of notifications with a given date, period
344: * and number of occurences.
345: * <P>
346: * If the timer notification to be inserted has a date that is before
347: * the current date, the method attempts to update the notification
348: * using the defined period. If the defined period is null, the method
349: * generates an exception.
350: * <P>
351: * If the timer notification has a non null period, the date of the
352: * notification is updated by adding the period until the notification
353: * date is later than the current date. The timer notification is then
354: * inserted into the list of notifications.
355: * <P>
356: * If the specified number of occurences is non null, the previous
357: * mechanism is employed. The number of times that the period is added
358: * is limited by the specified number of occurences. If the notification
359: * date remains earlier than the current date, an exception is generated.
360: * <P>
361: * Note that once the timer notification has been added into the list of
362: * notifications, its associated date, period and number of occurences
363: * cannot be updated.
364: *
365: * @param type The timer notification type.
366: *
367: * @param message The timer notification detailed message.
368: *
369: * @param userData The timer notification user data object.
370: *
371: * @param date The date when the notification occurs.
372: *
373: * @param period The period of the timer notification (in milliseconds).
374: *
375: * @param nbOccurences The total number the timer notification will be emitted.
376: *
377: * @return The identifier of the new created timer notification.
378: *
379: * @exception java.lang.IllegalArgumentException The period or the number
380: * of occurences is negative or the date notification is
381: * before the current date.
382: */
383: public Integer addNotification(String type, String message,
384: Object userData, Date date, long period, long nbOccurences)
385: throws IllegalArgumentException {
386: long nbOccurences_local = nbOccurences;
387:
388: if (date == null) {
389: throw new IllegalArgumentException(
390: "Timer notification date cannot be null!!!");
391: }
392:
393: // Negative periods and nbOccurences Not allowed
394: if (period < 0) {
395: throw new IllegalArgumentException(
396: "Period cannot be Negative");
397: }
398:
399: if (nbOccurences < 0) {
400: throw new IllegalArgumentException(
401: "Number of Occurences cannot be Zero");
402: }
403:
404: if ((date.before(new Date())) && (period == 0)) {
405: throw new IllegalArgumentException(
406: "Date specified is earlier than the current Date");
407:
408: } else if ((date.before(new Date())) && (period > 0)
409: && (nbOccurences > 0)) {
410: while (nbOccurences_local > 0) {
411: date = new Date(date.getTime() + period);
412: if (date.after(new Date())) {
413: break;
414: }
415: --nbOccurences_local;
416: }
417: if (date.before(new Date()))
418: throw new IllegalArgumentException(
419: "Date specified is earlier than the current Date");
420: } else if ((date.before(new Date())) && (period > 0)) {
421: log.trace("Date before currentDate and period > 0");
422: while (true) {
423: date = new Date(new Date().getTime() + period);
424: if (date.after(new Date()))
425: break;
426: }
427: }
428:
429: try {
430: if (objectName == null)
431: objectName = new ObjectName("Services", "type", "Timer");
432: } catch (Exception e) {
433: }
434:
435: if (scheduler == null)
436: scheduler = Scheduler.createScheduler(this .objectName
437: .toString(), 2);
438:
439: //create TimerNotification and Schedule a task to send that
440: Integer id = createNotificationID();
441:
442: TimerNotification timerNotification = new TimerNotification(id,
443: type, objectName, message, userData, date);
444:
445: Task task = new Task(timerNotification, period, nbOccurences);
446:
447: timerTable.put(id, task);
448: scheduler.scheduleTask(task, date);
449:
450: return id;
451: }
452:
453: /**
454: * This method gets all timer notification identifiers registered into
455: * the list of notifications.
456: *
457: * @return A vector of Integer objects containing all the timer
458: * notification identifiers. The vector is empty if there
459: * is no timer notification registered for this timer MBean.
460: */
461: public Vector getAllNotificationIDs() {
462: //return the Notification IDs
463: Vector vector = new Vector();
464: for (Enumeration e = timerTable.keys(); e.hasMoreElements();) {
465: vector.add(e.nextElement());
466: }
467: return vector;
468: }
469:
470: /**
471: * This method gets a copy of the date associated to a timer notification.
472: *
473: * @param id - The timer notification identifier.
474: *
475: * @return A copy of the date or null if the identifier is not mapped to
476: * any timer notification registered for this timer MBean.
477: */
478: public Date getDate(Integer id) {
479: Task task = (Task) timerTable.get(id);
480:
481: if (task != null)
482: return new Date(task.getTimerNotification().getTimeStamp());
483: else
484: return null;
485: }
486:
487: /**
488: * This method gets the number of timer notifications registered into the
489: * list of notifications.
490: *
491: * @return The number of timer notifications.
492: */
493: public int getNbNotifications() {
494: return timerTable.size();
495: }
496:
497: /**
498: * This method gets a copy of the remaining number of occurences
499: * associated to a timer notification.
500: *
501: * @param id - The timer notification identifier.
502: *
503: * @return A copy of the remaining number of occurences or null if
504: * the identifier is not mapped to any timer notification
505: * registered for this timer MBean.
506: */
507: public Long getNbOccurences(Integer id) {
508: return new Long(((Task) timerTable.get(id)).getNbOccurences());
509: }
510:
511: /**
512: * This method gets all the identifiers of timer notifications
513: * corresponding to the specified type.
514: *
515: * @param type - The timer notification type.
516: *
517: * @return A vector of <CODE>Integer</CODE> objects containing all the
518: * identifiers of timer notifications with the specified
519: * <CODE>type</CODE>. <BR>The vector is empty if there is no
520: * timer notifications registered for this timer MBean
521: * with the specified <CODE>type</CODE>.
522: */
523: public Vector getNotificationIDs(String type) {
524: Vector vector = new Vector();
525:
526: for (Enumeration e = timerTable.elements(); e.hasMoreElements();) {
527: TimerNotification timerNotification = ((Task) e
528: .nextElement()).getTimerNotification();
529: if (timerNotification.getType().equals(type)) {
530: vector.add(timerNotification.getNotificationID());
531: }
532: }
533: return vector;
534: }
535:
536: /**
537: * This method gets the timer notification detailed message corresponding
538: * to the specified identifier.
539: *
540: * @param id - The timer notification identifier.
541: *
542: * @return The timer notification detailed message or null if the
543: * identifier is not mapped to any timer notification
544: * registered for this timer MBean.
545: */
546: public String getNotificationMessage(Integer id) {
547: return ((Task) timerTable.get(id)).getTimerNotification()
548: .getMessage();
549: }
550:
551: /**
552: * This method gets the timer notification type corresponding to the
553: * specified identifier.
554: *
555: * @param id - The timer notification identifier.
556: *
557: * @return The timer notification type or null if the identifier is not
558: * mapped to any timer notification registered for this timer MBean.
559: */
560: public String getNotificationType(Integer id) {
561: return ((Task) timerTable.get(id)).getTimerNotification()
562: .getType();
563: }
564:
565: /**
566: * This method gets the timer notification user data object corresponding
567: * to the specified identifier.
568: *
569: * @param id - The timer notification identifier.
570: *
571: * @return The timer notification user data object or null if the
572: * identifier is not mapped to any timer notification
573: * registered for this timer MBean.
574: */
575: public Object getNotificationUserData(Integer id) {
576: return ((Task) timerTable.get(id)).getTimerNotification()
577: .getUserData();
578: }
579:
580: /**
581: * This method gets a copy of the period (in milliseconds) associated
582: * to a timer notification.
583: *
584: * @param id - The timer notification identifier.
585: *
586: * @return A copy of the period or null if the identifier is not mapped
587: * to any timer notification registered for this timer MBean.
588: */
589: public Long getPeriod(Integer id) {
590: return new Long(((Task) timerTable.get(id)).getPeriod());
591: }
592:
593: /**
594: * This method gets the flag indicating whether or not the timer
595: * sends past notifications.
596: *
597: * @return The past notifications sending on/off flag value.
598: */
599: public boolean getSendPastNotifications() {
600: return sendPastNotifications;
601: }
602:
603: /**
604: * This method tests whether the timer MBean is active. A timer MBean is
605: * marked active when the start method is called. It becomes inactive
606: * when the stop method is called.
607: *
608: * @return true if the timer MBean is active, false otherwise.
609: */
610: public boolean isActive() {
611: return active;
612: }
613:
614: /**
615: * This method tests whether the list of timer notifications is empty.
616: *
617: * @return true if the list of timer notifications is empty, false otherwise.
618: */
619: public boolean isEmpty() {
620: return timerTable.isEmpty();
621: }
622:
623: /**
624: * This method removes all the timer notifications from the list of
625: * notifications and resets the counter used to update the timer
626: * notification identifiers.
627: */
628: public void removeAllNotifications() {
629: for (Enumeration e = timerTable.keys(); e.hasMoreElements();) {
630: Task task = (Task) (timerTable.get(e.nextElement()));
631: scheduler.removeTask(task);
632: timerTable.remove(task.getTimerNotification()
633: .getNotificationID());
634: }
635:
636: timerTable.clear();
637: }
638:
639: /**
640: * This method Removes the timer notification corresponding to the
641: * specified identifier from the list of notifications.
642: *
643: * @param id - The timer notification identifier.
644: *
645: * @exception InstanceNotFoundException - The specified identifier does
646: * not correspond to any timer notification in the list
647: * of notifications of this timer MBean.
648: */
649: public void removeNotification(Integer id)
650: throws InstanceNotFoundException {
651: Task task = (Task) timerTable.get(id);
652:
653: if (task == null)
654: throw new InstanceNotFoundException(
655: "No such Notification in the list of Timer");
656:
657: scheduler.removeTask(task);
658: timerTable.remove(id);
659: }
660:
661: /**
662: * Removes all the timer notifications corresponding to the specified type
663: * from the list of notifications.
664: *
665: * @param type - The timer notification type.
666: *
667: * @exception InstanceNotFoundException - The specified type does not
668: * correspond to any timer notification in the list of
669: * notifications of this timer MBean.
670: */
671: public void removeNotifications(String type)
672: throws InstanceNotFoundException {
673: boolean temp = false;
674: for (Enumeration e = timerTable.keys(); e.hasMoreElements();) {
675: Task task = (Task) (timerTable.get(e.nextElement()));
676: if (task.getTimerNotification().getType().equals(type)) {
677: temp = true;
678: scheduler.removeTask(task);
679: timerTable.remove(task.getTimerNotification()
680: .getNotificationID());
681: }
682: }
683:
684: if (!temp)
685: throw new InstanceNotFoundException(
686: "No such Notification in the list of Timer");
687: }
688:
689: /**
690: * This method Sets the flag indicating whether the timer sends past
691: * notifications or not.
692: *
693: * @param value - The past notifications sending on/off flag value.
694: */
695: public void setSendPastNotifications(boolean value) {
696: sendPastNotifications = value;
697: }
698:
699: ////////////////////// Inner class for the Timer //////////////////////////
700:
701: class Task implements Runnable {
702: private TimerNotification timerNotification = null;
703: private long period = 0;
704: private long nbOccurences = 0;
705: private long sequenceNumber = 0;
706:
707: public Task(TimerNotification timerNotification, long period,
708: long nbOccurences) {
709: //new Throwable().printStackTrace();
710: this .timerNotification = timerNotification;
711: this .period = period;
712: this .nbOccurences = nbOccurences;
713:
714: if (period == 0 && nbOccurences == 1)
715: fromAddNotification = true;
716: }
717:
718: public void run() {
719: scheduler.removeTask(this );
720: //timerTable.remove(timerNotification.getNotificationID());
721: if ((period > 0) && (nbOccurences == 0)) {
722: //while(true)
723: //{
724: setTimerNotification();
725: sendNotification(timerNotification);
726: // try{
727: // Thread.sleep(period);
728: // }catch(InterruptedException e){
729: // }
730: //}
731:
732: //scheduler.removeTask(this);//iv
733: TimerNotification tn = clone(timerNotification);
734: this .timerNotification = tn;
735: //timerTable.put(timerNotification.getNotificationID(),this);
736: scheduler.scheduleTask(this , new Date(new Date()
737: .getTime()
738: + period));
739: //System.out.println(" Removing the id ................. ");
740: //timerTable.remove(timerNotification.getNotificationID());//iv
741: } else if ((period > 0) && (nbOccurences > 0)) {
742: //while(getNbOccurences()>0)
743: setTimerNotification();
744: sendNotification(timerNotification);
745: // try{
746: // Thread.sleep(period);
747: // }catch(InterruptedException e){
748: // }
749: nbOccurences = nbOccurences - 1;
750:
751: if (nbOccurences > 0) {
752: //construct a new TimerNotification object and schdule the task
753:
754: TimerNotification tn = clone(timerNotification);
755: this .timerNotification = tn;
756: //timerTable.put(timerNotification.getNotificationID(),this);
757: scheduler.scheduleTask(this , new Date(new Date()
758: .getTime()
759: + period));
760: } else {
761: timerTable.remove(timerNotification
762: .getNotificationID());
763: }
764: /*else if(nbOccurences == 0){
765: period = 0;
766: }*/
767:
768: } else if ((period == 0) && (nbOccurences == 0))
769: ;
770: else {
771: setTimerNotification();
772: sendNotification(timerNotification);
773: timerTable
774: .remove(timerNotification.getNotificationID());
775: }
776: }
777:
778: public synchronized TimerNotification getTimerNotification() {
779: return timerNotification;
780: }
781:
782: private synchronized void setTimerNotification() {
783: timerNotification.setSequenceNumber(sequenceNumber++);
784: timerNotification.setTimeStamp(new Date().getTime());
785: }
786:
787: public long getPeriod() {
788: return period;
789: }
790:
791: boolean fromAddNotification = false;
792:
793: public synchronized long getNbOccurences() {
794: if (fromAddNotification) {
795: return 0;
796: }
797: return nbOccurences;
798: }
799:
800: public synchronized long getOriginalNbOccurences() {
801: return nbOccurences;
802: }
803:
804: public synchronized void setNbOccurences(long l) {
805: nbOccurences = l;
806: }
807:
808: public void setSequenceNumber(long seqNumber) {
809: this .sequenceNumber = seqNumber;
810: }
811:
812: public TimerNotification clone(
813: TimerNotification timerNotification) {
814: TimerNotification tn = new TimerNotification(
815: timerNotification.getNotificationID(),
816: timerNotification.getType(),
817: (ObjectName) timerNotification.getSource(),
818: timerNotification.getMessage(), timerNotification
819: .getUserData(), new Date(timerNotification
820: .getTimeStamp()));
821: tn.setSequenceNumber(timerNotification.getSequenceNumber());
822: tn.setTimeStamp(timerNotification.getTimeStamp());
823: return tn;
824: }
825: }
826:
827: //---------------------------- Private method ----------------------------//
828:
829: /**
830: * Creates a Unique Notification Identifier
831: */
832: private Integer createNotificationID() {
833: return new Integer(++notificationID);
834: }
835:
836: /**
837: * Sends the past Notifications for the Timer.
838: */
839: private void sendExpiredNotifications(boolean sendPastNotifications) {
840: Enumeration e = timerTable.keys();
841:
842: for (; e.hasMoreElements();) {
843: Task t = (Task) (timerTable.get(e.nextElement()));
844: synchronized (t) {
845: if ((new Date(t.getTimerNotification().date))
846: .before(new Date())) {
847: long currTime = System.currentTimeMillis();
848:
849: if ((currTime > t.getTimerNotification()
850: .getTimeStamp())
851: && t.getOriginalNbOccurences() == 1) {
852: if (sendPastNotifications) {
853: t.getTimerNotification().setSequenceNumber(
854: 0);
855: t.getTimerNotification().setTimeStamp(
856: new Date().getTime());
857: sendNotification(t.getTimerNotification());
858: t.setSequenceNumber(1);
859: }
860:
861: timerTable.remove(t.getTimerNotification()
862: .getNotificationID());
863: scheduler.removeTask(t);
864: } else if ((currTime > t.getTimerNotification()
865: .getTimeStamp())
866: && (t.getPeriod() > 0)
867: && (t.getNbOccurences() == 0)) {
868: //to do : sendPastNotifications ...
869: } else if ((currTime > t.getTimerNotification()
870: .getTimeStamp())
871: && (t.getPeriod() > 0)) {
872: float pastNotifCount = (new Long(currTime
873: - t.getTimerNotification()
874: .getTimeStamp()).floatValue())
875: / new Long(t.getPeriod()).floatValue();
876:
877: long pastNotifCountInLong = new Float(
878: pastNotifCount).longValue();
879:
880: if (pastNotifCount > new Long(
881: pastNotifCountInLong).floatValue())
882: pastNotifCountInLong += 1;
883:
884: //riskey code: need to change it later, Hyther
885: if ((t.getNbOccurences() - pastNotifCountInLong) < 1)
886: pastNotifCountInLong -= 1;
887:
888: t.setNbOccurences(t.getNbOccurences()
889: - pastNotifCountInLong);
890:
891: if (sendPastNotifications) {
892: long i = 0;
893: for (; i < pastNotifCountInLong; i++) {
894: TimerNotification timerNotif = t
895: .clone(t.getTimerNotification());
896: timerNotif.setSequenceNumber(i);
897: timerNotif.setTimeStamp(new Date()
898: .getTime());
899: sendNotification(timerNotif);
900: }
901: t.setSequenceNumber(i);
902: }
903: }
904: }
905: }
906: }
907: }
908: }//End the Timer class.
|