1 7 8 package javax.management.timer; 9 10 11 12 import java.util.Date ; 15 import java.util.Enumeration ; 16 import java.util.Hashtable ; 17 import java.util.Iterator ; 18 import java.util.Set ; 19 import java.util.TreeSet ; 20 import java.util.Vector ; 21 22 import javax.management.MBeanNotificationInfo ; 25 import javax.management.MBeanRegistration ; 26 import javax.management.MBeanServer ; 27 import javax.management.NotificationBroadcasterSupport ; 28 import javax.management.ObjectName ; 29 import javax.management.InstanceNotFoundException ; 30 31 import com.sun.jmx.trace.Trace; 32 33 71 public class Timer extends NotificationBroadcasterSupport 72 implements TimerMBean , MBeanRegistration { 73 74 75 80 81 85 public static final long ONE_SECOND = 1000; 86 87 91 public static final long ONE_MINUTE = 60*ONE_SECOND; 92 93 97 public static final long ONE_HOUR = 60*ONE_MINUTE; 98 99 103 public static final long ONE_DAY = 24*ONE_HOUR; 104 105 109 public static final long ONE_WEEK = 7*ONE_DAY; 110 111 112 115 boolean isTraceOn() { 116 return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_TIMER); 117 } 118 119 void trace(String clz, String func, String info) { 120 Trace.send(Trace.LEVEL_TRACE, Trace.INFO_TIMER, clz, func, info); 121 } 122 123 void trace(String func, String 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 clz, String func, String info) { 132 Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_TIMER, clz, func, info); 133 } 134 135 void debug(String func, String info) { 136 debug(dbgTag, func, info); 137 } 138 139 140 145 146 private static final String dbgTag = "Timer"; 147 148 152 private Hashtable timerTable = new Hashtable (); 153 154 159 private boolean sendPastNotifications = false; 160 161 165 private transient boolean isActive = false; 166 167 171 private transient long sequenceNumber = 0; 172 173 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 186 private int counterID = 0; 187 188 private java.util.Timer timer; 189 190 195 196 199 public Timer() { 200 } 201 202 207 208 221 public ObjectName preRegister(MBeanServer server, ObjectName name) 222 throws java.lang.Exception { 223 return name; 224 } 225 226 232 public void postRegister (Boolean registrationDone) { 233 } 234 235 243 public void preDeregister() throws java.lang.Exception { 244 245 if (isTraceOn()) { 246 trace("preDeregister", "stop the timer"); 247 } 248 249 stop(); 252 } 253 254 260 public void postDeregister() { 261 } 262 263 271 public synchronized MBeanNotificationInfo [] getNotificationInfo() { 272 Set notifTypes = new TreeSet (); 273 for (Iterator it = timerTable.values().iterator(); it.hasNext(); ) { 274 Object [] entry = (Object []) it.next(); 275 TimerNotification notif = (TimerNotification ) 276 entry[TIMER_NOTIF_INDEX]; 277 notifTypes.add(notif.getType()); 278 } 279 String [] notifTypesArray = (String []) 280 notifTypes.toArray(new String [0]); 281 return new MBeanNotificationInfo [] { 282 new MBeanNotificationInfo (notifTypesArray, 283 TimerNotification .class.getName(), 284 "Notification sent by Timer MBean") 285 }; 286 } 287 288 297 public synchronized void start() { 298 299 if (isTraceOn()) { 300 trace("start", "starting the timer"); 301 } 302 303 if (isActive == false) { 306 307 timer = new java.util.Timer (); 308 309 TimerAlarmClock alarmClock; 310 Object [] obj; 311 Date date; 312 313 Date currentDate = new Date (); 314 315 sendPastNotifications(currentDate, sendPastNotifications); 320 321 Enumeration e = timerTable.elements(); 325 while (e.hasMoreElements()) { 326 327 obj = (Object [])e.nextElement(); 328 329 date = (Date )obj[TIMER_DATE_INDEX]; 332 333 boolean fixedRate = ((Boolean )obj[FIXED_RATE_INDEX]).booleanValue(); 336 if (fixedRate) 337 { 338 alarmClock = new TimerAlarmClock (this, date); 339 obj[ALARM_CLOCK_INDEX] = (Object )alarmClock; 340 timer.schedule(alarmClock, alarmClock.next); 341 } 342 else 343 { 344 alarmClock = new TimerAlarmClock (this, (date.getTime() - currentDate.getTime())); 345 obj[ALARM_CLOCK_INDEX] = (Object )alarmClock; 346 timer.schedule(alarmClock, alarmClock.timeout); 347 } 348 } 349 350 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 367 public synchronized void stop() { 368 369 if (isTraceOn()) { 370 trace("stop", "stoping the timer"); 371 } 372 373 if (isActive == true) { 376 377 TimerAlarmClock alarmClock; 378 Object [] obj; 379 380 Enumeration e = timerTable.elements(); 381 while (e.hasMoreElements()) { 382 383 obj = (Object [])e.nextElement(); 384 385 alarmClock = (TimerAlarmClock )obj[ALARM_CLOCK_INDEX]; 388 if (alarmClock != null) { 389 400 alarmClock.cancel(); 401 alarmClock = null; 402 } 403 } 404 405 timer.cancel(); 406 407 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 456 461 public synchronized Integer addNotification(String type, String message, Object userData, 462 Date date, long period, long nbOccurences, boolean fixedRate) 463 throws java.lang.IllegalArgumentException { 464 465 if (date == null) { 466 throw new java.lang.IllegalArgumentException ("Timer notification date cannot be null."); 467 } 468 469 472 if ((period < 0) || (nbOccurences < 0)) { 476 throw new java.lang.IllegalArgumentException ("Negative values for the periodicity"); 477 } 478 479 Date currentDate = new Date (); 480 481 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 Integer notifID = null; 495 notifID = new Integer (++counterID); 496 497 TimerNotification notif = new TimerNotification (type, this, 0, 0, message, notifID); 501 notif.setUserData(userData); 502 503 Object [] obj = new Object [6]; 504 505 TimerAlarmClock alarmClock; 506 if (fixedRate) 507 { 508 alarmClock = new TimerAlarmClock (this, date); 509 } 510 else 511 { 512 alarmClock = new TimerAlarmClock (this, (date.getTime() - currentDate.getTime())); 513 } 514 515 Date d = new Date (date.getTime()); 519 520 obj[TIMER_NOTIF_INDEX] = (Object )notif; 521 obj[TIMER_DATE_INDEX] = (Object )d; 522 obj[TIMER_PERIOD_INDEX] = (Object ) new Long (period); 523 obj[TIMER_NB_OCCUR_INDEX] = (Object ) new Long (nbOccurences); 524 obj[ALARM_CLOCK_INDEX] = (Object )alarmClock; 525 obj[FIXED_RATE_INDEX] = new Boolean (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 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 590 595 public synchronized Integer addNotification(String type, String message, Object userData, 596 Date date, long period, long nbOccurences) 597 throws java.lang.IllegalArgumentException { 598 599 return addNotification(type, message, userData, date, period, nbOccurences, false); 600 } 601 602 628 633 public synchronized Integer addNotification(String type, String message, Object userData, 634 Date date, long period) 635 throws java.lang.IllegalArgumentException { 636 637 return (addNotification(type, message, userData, date, period, 0)); 638 } 639 640 660 665 public synchronized Integer addNotification(String type, String message, Object userData, Date date) 666 throws java.lang.IllegalArgumentException { 667 668 669 return (addNotification(type, message, userData, date, 0, 0)); 670 } 671 672 680 public synchronized void removeNotification(Integer id) throws InstanceNotFoundException { 681 682 if (timerTable.containsKey(id) == false) { 685 throw new InstanceNotFoundException ("Timer notification to remove not in the list of notifications"); 686 } 687 688 Object [] obj = (Object [])timerTable.get(id); 691 TimerAlarmClock alarmClock = (TimerAlarmClock )obj[ALARM_CLOCK_INDEX]; 692 if (alarmClock != null) { 693 alarmClock.cancel(); 704 alarmClock = null; 705 } 706 707 if (isTraceOn()) { 710 trace("removeNotification", "removing timer notification:" + 711 "\n\tNotification source = " + ((TimerNotification )obj[TIMER_NOTIF_INDEX]).getSource() + 712 "\n\tNotification type = " + ((TimerNotification )obj[TIMER_NOTIF_INDEX]).getType() + 713 "\n\tNotification ID = " + ((TimerNotification )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 735 public synchronized void removeNotifications(String type) throws InstanceNotFoundException { 736 737 TimerNotification notif; 738 Integer id; 739 TimerAlarmClock alarmClock; 740 Object [] obj; 741 742 Vector v = getNotificationIDs(type); 743 744 if (v.isEmpty()) { 747 throw new InstanceNotFoundException ("Timer notifications to remove not in the list of notifications"); 748 } 749 750 Enumeration e = v.elements(); 751 while (e.hasMoreElements()) { 752 notif = (TimerNotification )e.nextElement(); 753 id = notif.getNotificationID(); 754 obj = (Object [])timerTable.get(id); 755 756 timerTable.remove(id); 757 758 alarmClock = (TimerAlarmClock )obj[ALARM_CLOCK_INDEX]; 759 if (alarmClock != null) { 760 alarmClock.cancel(); 761 } 762 } 763 } 764 765 769 public synchronized void removeAllNotifications() { 770 771 Object [] obj; 772 TimerAlarmClock alarmClock; 773 774 Enumeration e = timerTable.elements(); 775 while (e.hasMoreElements()) { 776 777 obj = (Object [])e.nextElement(); 778 779 alarmClock = (TimerAlarmClock )obj[ALARM_CLOCK_INDEX]; 782 alarmClock.cancel(); 795 alarmClock = null; 796 } 797 798 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 counterID = 0; 813 814 if (isTraceOn()) { 815 trace("removeAllNotifications", "timer notification counter ID resetted"); 816 } 817 } 818 819 822 827 public int getNbNotifications() { 828 return timerTable.size(); 829 } 830 831 837 public synchronized Vector getAllNotificationIDs() { 838 839 Vector v = new Vector (); 840 841 Enumeration e = timerTable.keys(); 842 while (e.hasMoreElements()) { 843 844 v.addElement((Integer )e.nextElement()); 845 } 846 return v; 847 } 848 849 859 public synchronized Vector getNotificationIDs(String type) { 860 861 Object [] obj; 862 String s; 863 864 Vector v = new Vector (); 865 866 Enumeration e = timerTable.elements(); 867 868 if (type == null) { 871 while (e.hasMoreElements()) { 872 obj = (Object [])e.nextElement(); 873 s = ((TimerNotification )obj[TIMER_NOTIF_INDEX]).getType(); 874 875 if (s == null) { 876 v.addElement((TimerNotification )obj[TIMER_NOTIF_INDEX]); 877 } 878 } 879 } 880 else { 881 while (e.hasMoreElements()) { 882 obj = (Object [])e.nextElement(); 883 s = ((TimerNotification )obj[TIMER_NOTIF_INDEX]).getType(); 884 885 if (type.equals(s)) { 886 v.addElement((TimerNotification )obj[TIMER_NOTIF_INDEX]); 887 } 888 } 889 } 890 return v; 891 } 892 893 901 public String getNotificationType(Integer id) { 902 903 Object [] obj = (Object [])timerTable.get(id); 904 if (obj != null) { 905 return ( (String )((TimerNotification )obj[TIMER_NOTIF_INDEX]).getType() ); 906 } 907 return null; 908 } 909 910 918 public String getNotificationMessage(Integer id) { 919 920 Object [] obj = (Object [])timerTable.get(id); 921 if (obj != null) { 922 return ( (String )((TimerNotification )obj[TIMER_NOTIF_INDEX]).getMessage() ); 923 } 924 return null; 925 } 926 927 935 939 public Object getNotificationUserData(Integer id) { 940 Object [] obj = (Object [])timerTable.get(id); 941 if (obj != null) { 942 return ( ((TimerNotification )obj[TIMER_NOTIF_INDEX]).getUserData() ); 943 } 944 return null; 945 } 946 947 955 public Date getDate(Integer id) { 956 957 Object [] obj = (Object [])timerTable.get(id); 958 if (obj != null) { 959 Date date = (Date )obj[TIMER_DATE_INDEX]; 960 return (new Date (date.getTime())); 961 } 962 return null; 963 } 964 965 973 public Long getPeriod(Integer id) { 974 975 Object [] obj = (Object [])timerTable.get(id); 976 if (obj != null) { 977 Long period = (Long )obj[TIMER_PERIOD_INDEX]; 978 return (new Long (period.longValue())); 979 } 980 return null; 981 } 982 983 991 public Long getNbOccurences(Integer id) { 992 993 Object [] obj = (Object [])timerTable.get(id); 994 if (obj != null) { 995 Long nbOccurences = (Long )obj[TIMER_NB_OCCUR_INDEX]; 996 return (new Long (nbOccurences.longValue())); 997 } 998 return null; 999 } 1000 1001 1010 public Boolean getFixedRate(Integer id) { 1011 1012 Object [] obj = (Object [])timerTable.get(id); 1013 if (obj != null) { 1014 Boolean fixedRate = (Boolean )obj[FIXED_RATE_INDEX]; 1015 return (new Boolean (fixedRate.booleanValue())); 1016 } 1017 return null; 1018 } 1019 1020 1028 public boolean getSendPastNotifications() { 1029 return sendPastNotifications; 1030 } 1031 1032 1040 public void setSendPastNotifications(boolean value) { 1041 sendPastNotifications = value; 1042 } 1043 1044 1052 public boolean isActive() { 1053 return isActive; 1054 } 1055 1056 1061 public boolean isEmpty() { 1062 return (timerTable.isEmpty()); 1063 } 1064 1065 1070 1071 1077 private synchronized void sendPastNotifications(Date currentDate, boolean currentFlag) { 1078 1079 TimerNotification notif; 1080 Integer notifID; 1081 Date date; 1082 Object [] obj; 1083 1084 Enumeration e = timerTable.elements(); 1085 while (e.hasMoreElements()) { 1086 1087 obj = (Object [])e.nextElement(); 1088 1089 notif = (TimerNotification )obj[TIMER_NOTIF_INDEX]; 1092 notifID = notif.getNotificationID(); 1093 date = (Date )obj[TIMER_DATE_INDEX]; 1094 1095 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 updateTimerTable(notif.getNotificationID()); 1122 } 1123 } 1124 } 1125 1126 1139 private synchronized void updateTimerTable(Integer notifID) { 1140 1141 Object [] obj = (Object [])timerTable.get(notifID); 1144 Date date = (Date )obj[TIMER_DATE_INDEX]; 1145 Long period = (Long )obj[TIMER_PERIOD_INDEX]; 1146 Long nbOccurences = (Long )obj[TIMER_NB_OCCUR_INDEX]; 1147 Boolean fixedRate = (Boolean )obj[FIXED_RATE_INDEX]; 1148 TimerAlarmClock alarmClock = (TimerAlarmClock )obj[ALARM_CLOCK_INDEX]; 1149 1150 if (period.longValue() != 0) { 1151 1152 if ((nbOccurences.longValue() == 0) || (nbOccurences.longValue() > 1)) { 1160 1161 date.setTime(date.getTime() + period.longValue()); 1162 obj[TIMER_NB_OCCUR_INDEX] = new Long (java.lang.Math.max(0L, (nbOccurences.longValue() - 1))); 1163 nbOccurences = (Long )obj[TIMER_NB_OCCUR_INDEX]; 1164 1165 if (isActive == true) { 1166 if (fixedRate.booleanValue()) 1167 { 1168 alarmClock = new TimerAlarmClock (this, date); 1169 obj[ALARM_CLOCK_INDEX] = (Object )alarmClock; 1170 timer.schedule(alarmClock, alarmClock.next); 1171 } 1172 else 1173 { 1174 alarmClock = new TimerAlarmClock (this, period.longValue()); 1175 obj[ALARM_CLOCK_INDEX] = (Object )alarmClock; 1176 timer.schedule(alarmClock, alarmClock.timeout); 1177 } 1178 } 1179 if (isTraceOn()) { 1180 TimerNotification notif = (TimerNotification )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.cancel(); 1202 alarmClock = null; 1205 } 1206 timerTable.remove(notifID); 1207 } 1208 } 1209 else { 1210 if (alarmClock != null) { 1211 1220 alarmClock.cancel(); 1221 1222 alarmClock = null; 1225 } 1226 timerTable.remove(notifID); 1227 } 1228 } 1229 1230 1235 1236 1242 void notifyAlarmClock(TimerAlarmClockNotification notification) { 1243 1244 Object [] obj; 1245 TimerNotification timerNotification = null; 1246 Date timerDate = null; 1247 1248 TimerAlarmClock alarmClock = (TimerAlarmClock )notification.getSource(); 1251 1252 Enumeration e = timerTable.elements(); 1253 while (e.hasMoreElements()) { 1254 obj = (Object [])e.nextElement(); 1255 if (obj[ALARM_CLOCK_INDEX] == alarmClock) { 1256 timerNotification = (TimerNotification )obj[TIMER_NOTIF_INDEX]; 1257 timerDate = (Date )obj[TIMER_DATE_INDEX]; 1258 break; 1259 } 1260 } 1261 1262 sendNotification(timerDate, timerNotification); 1265 1266 updateTimerTable(timerNotification.getNotificationID()); 1269 } 1270 1271 1278 void sendNotification(Date timeStamp, TimerNotification 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 )notification.cloneTimerNotification()); 1296 } 1297 1298 if (isTraceOn()) { 1299 trace("sendNotification", "timer notification sent"); 1300 } 1301 } 1302} 1303 1304 1310 1311class TimerAlarmClock extends java.util.TimerTask { 1312 1313 Timer listener = null; 1314 long timeout = 10000; 1315 Date next = null; 1316 1317 1322 1323 public TimerAlarmClock(Timer listener, long timeout) { 1324 this.listener = listener; 1325 this.timeout = Math.max(0L, timeout); 1326 } 1327 1328 public TimerAlarmClock(Timer listener, Date next) { 1329 this.listener = listener; 1330 this.next = next; 1331 } 1332 1333 1338 1339 1342 public void run() { 1343 1344 try { 1345 TimerAlarmClockNotification notif = new TimerAlarmClockNotification (this); 1347 listener.notifyAlarmClock(notif); 1348 } catch (Exception 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 |