| 1 2 18 19 22 package org.quartz; 23 24 import org.quartz.Job; 25 import org.quartz.JobExecutionContext; 26 import org.quartz.JobExecutionException; 27 import org.quartz.Scheduler; 28 import org.quartz.SimpleTrigger; 29 import org.quartz.Trigger; 30 import org.quartz.CronTrigger; 31 32 import java.util.Calendar ; 33 import java.util.Date ; 34 import java.util.HashMap ; 35 import java.util.Iterator ; 36 import java.util.Map ; 37 import java.util.Set ; 38 import java.util.SortedSet ; 39 import java.util.TimeZone ; 40 import java.util.TreeSet ; 41 import java.text.ParseException ; 42 43 148 public class UICronTrigger extends Trigger { 149 150 157 158 165 public static final int MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1; 166 167 175 public static final int MISFIRE_INSTRUCTION_DO_NOTHING = 2; 176 177 184 private static final int ALL_SPEC_INT = 99; 186 private static final int NO_SPEC_INT = 98; 188 private static final Integer ALL_SPEC = new Integer (ALL_SPEC_INT); 189 190 private static final Integer NO_SPEC = new Integer (NO_SPEC_INT); 191 192 private static Map monthMap = new HashMap (20); 193 194 private static Map dayMap = new HashMap (60); 195 196 static { 197 monthMap.put("JAN", new Integer (0)); 198 monthMap.put("FEB", new Integer (1)); 199 monthMap.put("MAR", new Integer (2)); 200 monthMap.put("APR", new Integer (3)); 201 monthMap.put("MAY", new Integer (4)); 202 monthMap.put("JUN", new Integer (5)); 203 monthMap.put("JUL", new Integer (6)); 204 monthMap.put("AUG", new Integer (7)); 205 monthMap.put("SEP", new Integer (8)); 206 monthMap.put("OCT", new Integer (9)); 207 monthMap.put("NOV", new Integer (10)); 208 monthMap.put("DEC", new Integer (11)); 209 210 dayMap.put("SUN", new Integer (1)); 211 dayMap.put("MON", new Integer (2)); 212 dayMap.put("TUE", new Integer (3)); 213 dayMap.put("WED", new Integer (4)); 214 dayMap.put("THU", new Integer (5)); 215 dayMap.put("FRI", new Integer (6)); 216 dayMap.put("SAT", new Integer (7)); 217 } 218 219 private Date startTime = null; 220 221 private Date endTime = null; 222 223 private Date nextFireTime = null; 224 225 private TimeZone timeZone = null; 226 227 private Date previousFireTime = null; 228 229 private TreeSet seconds = null; 230 231 private TreeSet minutes = null; 232 233 private TreeSet hours = null; 234 235 private TreeSet daysOfMonth = null; 236 237 private TreeSet months = null; 238 239 private TreeSet daysOfWeek = null; 240 241 private TreeSet years = null; 242 243 private transient boolean lastdayOfWeek = false; 244 245 private transient int nthdayOfWeek = 0; 246 247 private transient boolean lastdayOfMonth = false; 248 249 private transient boolean calendardayOfWeek = false; 250 251 private transient boolean calendardayOfMonth = false; 252 253 260 261 public void reset() { 262 seconds = new TreeSet (); 263 minutes = new TreeSet (); 264 hours = new TreeSet (); 265 daysOfMonth = new TreeSet (); 266 months = new TreeSet (); 267 daysOfWeek = new TreeSet (); 268 years = new TreeSet (); 269 270 seconds.add(new Integer (0)); 272 273 minutes.add(ALL_SPEC); 274 for (int i = 0; i < 60; i++) 275 minutes.add(new Integer (i)); 276 277 hours.add(ALL_SPEC); 278 for (int i = 0; i < 24; i++) 279 hours.add(new Integer (i)); 280 281 daysOfMonth.add(ALL_SPEC); 282 for (int i = 1; i <= 31; i++) 283 daysOfMonth.add(new Integer (i)); 284 285 months.add(ALL_SPEC); 286 for (int i = 1; i <= 12; i++) 287 months.add(new Integer (i)); 288 289 daysOfWeek.add(NO_SPEC); 290 291 years.add(ALL_SPEC); 292 for (int i = 1970; i <= 2099; i++) 293 years.add(new Integer (i)); 294 295 startTime = new Date (); 296 setStartTime(startTime); 297 setTimeZone(TimeZone.getDefault()); 298 } 299 300 305 public UICronTrigger() { 306 super(); 307 reset(); 308 } 309 310 315 public UICronTrigger(String name, String group) { 316 super(name, group); 317 reset(); 318 } 319 320 326 public UICronTrigger(String name, String group, String jobName, 327 String jobGroup) { 328 super(name, group, jobName, jobGroup); 329 reset(); 330 } 331 332 339 340 345 public Date getStartTime() { 346 return this.startTime; 347 } 348 349 public void setStartTime(Date startTime) { 350 if (startTime == null) 351 throw new IllegalArgumentException ("Start time cannot be null"); 352 353 Date eTime = getEndTime(); 354 if (eTime != null && startTime != null && eTime.before(startTime)) 355 throw new IllegalArgumentException ( 356 "End time cannot be before start time"); 357 358 359 Calendar cl = Calendar.getInstance(); 364 cl.setTime(startTime); 365 cl.set(Calendar.MILLISECOND, 0); 366 367 this.startTime = cl.getTime(); 368 } 369 370 378 public Date getEndTime() { 379 return this.endTime; 380 } 381 382 public void setEndTime(Date endTime) { 383 Date sTime = getStartTime(); 384 if (sTime != null && endTime != null && sTime.after(endTime)) 385 throw new IllegalArgumentException ( 386 "End time cannot be before start time"); 387 388 this.endTime = endTime; 389 } 390 391 399 public Date getNextFireTime() { 400 return this.nextFireTime; 401 } 402 403 public void updateAfterMisfire(org.quartz.Calendar cal) { 404 int instr = getMisfireInstruction(); 405 406 if (instr == MISFIRE_INSTRUCTION_SMART_POLICY) 407 instr = MISFIRE_INSTRUCTION_DO_NOTHING; 408 409 if (instr == MISFIRE_INSTRUCTION_DO_NOTHING) { 410 Date newFireTime = getFireTimeAfter(new Date ()); 411 while (newFireTime != null && cal != null 412 && !cal.isTimeIncluded(newFireTime.getTime())) { 413 newFireTime = getFireTimeAfter(newFireTime); 414 } 415 416 setNextFireTime(newFireTime); 417 418 } else if (instr == MISFIRE_INSTRUCTION_FIRE_ONCE_NOW) { 419 setNextFireTime(new Date ()); 420 } 421 } 422 423 public Date getPreviousFireTime() { 424 return this.previousFireTime; 425 } 426 427 436 public void setPreviousFireTime(Date previousFireTime) { 437 this.previousFireTime = previousFireTime; 438 } 439 440 446 public void setNextFireTime(Date nextFireTime) { 447 this.nextFireTime = nextFireTime; 448 } 449 450 456 public TimeZone getTimeZone() { 457 return this.timeZone; 458 } 459 460 466 public void setTimeZone(TimeZone timeZone) { 467 this.timeZone = timeZone; 468 } 469 470 482 public Date getFireTimeAfter(Date afterTime) { 483 if (afterTime == null) afterTime = new Date (); 484 485 if (startTime.after(afterTime)) 486 afterTime = new Date (startTime.getTime() - 1000l); 487 488 Date pot = getTimeAfter(afterTime); 489 if (endTime != null && pot != null && pot.after(endTime)) return null; 490 491 return pot; 492 } 493 494 505 public Date getFinalFireTime() { 506 if (this.endTime != null) return getTimeBefore(this.endTime); 507 else 508 return null; 509 } 510 511 517 public boolean mayFireAgain() { 518 return (getNextFireTime() != null); 519 } 520 521 protected boolean validateMisfireInstruction(int misfireInstruction) { 522 if (misfireInstruction < MISFIRE_INSTRUCTION_SMART_POLICY) 523 return false; 524 525 if (misfireInstruction > MISFIRE_INSTRUCTION_DO_NOTHING) return false; 526 527 return true; 528 } 529 530 545 public void updateAfterMisfire() { 546 int instr = getMisfireInstruction(); 547 548 if (instr == MISFIRE_INSTRUCTION_SMART_POLICY) 549 instr = MISFIRE_INSTRUCTION_DO_NOTHING; 550 551 if (instr == MISFIRE_INSTRUCTION_DO_NOTHING) { 552 setNextFireTime(getFireTimeAfter(new Date ())); 553 } else if (instr == MISFIRE_INSTRUCTION_FIRE_ONCE_NOW) { 554 setNextFireTime(new Date ()); 555 } 556 } 557 558 569 public boolean willFireOn(Calendar test) { 570 Integer second = new Integer (test.get(Calendar.SECOND)); 571 Integer minute = new Integer (test.get(Calendar.MINUTE)); 572 Integer hour = new Integer (test.get(Calendar.HOUR_OF_DAY)); 573 Integer day = new Integer (test.get(Calendar.DAY_OF_MONTH)); 574 Integer month = new Integer (test.get(Calendar.MONTH)); 575 576 if ((seconds.contains(second) || seconds.contains(ALL_SPEC)) 577 && (minutes.contains(minute) || minutes.contains(ALL_SPEC)) 578 && (hours.contains(hour) || hours.contains(ALL_SPEC)) 579 && (daysOfMonth.contains(day) || daysOfMonth.contains(ALL_SPEC)) 580 && (months.contains(month) || months.contains(ALL_SPEC))) { 581 582 return true; } 583 584 return false; 585 } 586 587 608 public int executionComplete(JobExecutionContext context, 609 JobExecutionException result) { 610 if (result != null && result.refireImmediately()) 611 return Trigger.INSTRUCTION_RE_EXECUTE_JOB; 612 613 if (result != null && result.refireImmediately()) 614 return INSTRUCTION_RE_EXECUTE_JOB; 615 616 if (result != null && result.unscheduleFiringTrigger()) 617 return INSTRUCTION_SET_TRIGGER_COMPLETE; 618 619 if (result != null && result.unscheduleAllTriggers()) 620 return INSTRUCTION_SET_ALL_JOB_TRIGGERS_COMPLETE; 621 622 if (!mayFireAgain()) return INSTRUCTION_DELETE_TRIGGER; 623 624 return INSTRUCTION_NOOP; 625 } 626 627 637 public void triggered(org.quartz.Calendar calendar) { 638 previousFireTime = nextFireTime; 639 nextFireTime = getFireTimeAfter(nextFireTime); 640 641 while (nextFireTime != null && calendar != null 642 && !calendar.isTimeIncluded(nextFireTime.getTime())) { 643 nextFireTime = getFireTimeAfter(nextFireTime); 644 } 645 } 646 647 651 public void updateWithNewCalendar(org.quartz.Calendar calendar, long misfireThreshold) 652 { 653 nextFireTime = getFireTimeAfter(previousFireTime); 654 655 Date now = new Date (); 656 do { 657 while (nextFireTime != null && calendar != null 658 && !calendar.isTimeIncluded(nextFireTime.getTime())) { 659 nextFireTime = getFireTimeAfter(nextFireTime); 660 } 661 662 if(nextFireTime != null && nextFireTime.before(now)) { 663 long diff = now.getTime() - nextFireTime.getTime(); 664 if(diff >= misfireThreshold) { 665 nextFireTime = getFireTimeAfter(nextFireTime); 666 continue; 667 } 668 } 669 }while(false); 670 } 671 672 689 public Date computeFirstFireTime(org.quartz.Calendar calendar) { 690 nextFireTime = getFireTimeAfter(new Date (startTime.getTime() - 1000l)); 691 692 while (nextFireTime != null && calendar != null 693 && !calendar.isTimeIncluded(nextFireTime.getTime())) { 694 nextFireTime = getFireTimeAfter(nextFireTime); 695 } 696 697 return nextFireTime; 698 } 699 700 public String getExpressionSummary() { 701 StringBuffer buf = new StringBuffer (); 702 703 buf.append("seconds: "); 704 buf.append(getExpressionSetSummary(seconds)); 705 buf.append("\n"); 706 buf.append("minutes: "); 707 buf.append(getExpressionSetSummary(minutes)); 708 buf.append("\n"); 709 buf.append("hours: "); 710 buf.append(getExpressionSetSummary(hours)); 711 buf.append("\n"); 712 buf.append("daysOfMonth: "); 713 buf.append(getExpressionSetSummary(daysOfMonth)); 714 buf.append("\n"); 715 buf.append("months: "); 716 buf.append(getExpressionSetSummary(months)); 717 buf.append("\n"); 718 buf.append("daysOfWeek: "); 719 buf.append(getExpressionSetSummary(daysOfWeek)); 720 buf.append("\n"); 721 buf.append("lastdayOfWeek: "); 722 buf.append(lastdayOfWeek); 723 buf.append("\n"); 724 buf.append("lastdayOfMonth: "); 725 buf.append(lastdayOfMonth); 726 buf.append("\n"); 727 buf.append("calendardayOfWeek: "); 728 buf.append(calendardayOfWeek); 729 buf.append("\n"); 730 buf.append("calendardayOfMonth: "); 731 buf.append(calendardayOfMonth); 732 buf.append("\n"); 733 buf.append("years: "); 734 buf.append(getExpressionSetSummary(years)); 735 buf.append("\n"); 736 737 return buf.toString(); 738 } 739 740 private String getExpressionSetSummary(Set set) { 741 742 if (set.contains(NO_SPEC)) return "?"; 743 if (set.contains(ALL_SPEC)) return "*"; 744 745 StringBuffer buf = new StringBuffer (); 746 747 Iterator itr = set.iterator(); 748 boolean first = true; 749 while (itr.hasNext()) { 750 Integer iVal = (Integer ) itr.next(); 751 String val = iVal.toString(); 752 if (!first) buf.append(","); 753 buf.append(val); 754 first = false; 755 } 756 757 return buf.toString(); 758 } 759 760 766 private Date getTimeAfter(Date afterTime) { 767 Calendar cl = Calendar.getInstance(timeZone); 768 769 afterTime = new Date (afterTime.getTime() + 1000); 772 cl.setTime(afterTime); 774 cl.set(Calendar.MILLISECOND, 0); 775 776 boolean gotOne = false; 777 778 while (!gotOne) { 780 781 if (endTime != null && cl.getTime().after(endTime)) return null; 782 783 SortedSet st = null; 784 int t = 0; 785 786 int sec = cl.get(Calendar.SECOND); 787 int min = cl.get(Calendar.MINUTE); 788 789 st = seconds.tailSet(new Integer (sec)); 791 if (st != null && st.size() != 0) { 792 sec = ((Integer ) st.first()).intValue(); 793 } else { 794 sec = ((Integer ) seconds.first()).intValue(); 795 min++; 796 cl.set(Calendar.MINUTE, min); 797 } 798 cl.set(Calendar.SECOND, sec); 799 800 min = cl.get(Calendar.MINUTE); 801 int hr = cl.get(Calendar.HOUR_OF_DAY); 802 t = -1; 803 804 st = minutes.tailSet(new Integer (min)); 806 if (st != null && st.size() != 0) { 807 t = min; 808 min = ((Integer ) st.first()).intValue(); 809 } else { 810 min = ((Integer ) minutes.first()).intValue(); 811 hr++; 812 } 813 if (min != t) { 814 cl.set(Calendar.SECOND, 0); 815 cl.set(Calendar.MINUTE, min); 816 cl.set(Calendar.HOUR_OF_DAY, hr); 817 continue; 818 } 819 cl.set(Calendar.MINUTE, min); 820 821 hr = cl.get(Calendar.HOUR_OF_DAY); 822 int day = cl.get(Calendar.DAY_OF_MONTH); 823 t = -1; 824 825 st = hours.tailSet(new Integer (hr)); 827 if (st != null && st.size() != 0) { 828 t = hr; 829 hr = ((Integer ) st.first()).intValue(); 830 } else { 831 hr = ((Integer ) hours.first()).intValue(); 832 day++; 833 } 834 if (hr != t) { 835 cl.set(Calendar.SECOND, 0); 836 cl.set(Calendar.MINUTE, 0); 837 cl.set(Calendar.HOUR_OF_DAY, hr); 838 cl.set(Calendar.DAY_OF_MONTH, day); 839 continue; 840 } 841 cl.set(Calendar.HOUR_OF_DAY, hr); 842 843 day = cl.get(Calendar.DAY_OF_MONTH); 844 int mon = cl.get(Calendar.MONTH) + 1; t = -1; 848 849 boolean dayOfMSpec = !daysOfMonth.contains(NO_SPEC); 851 boolean dayOfWSpec = !daysOfWeek.contains(NO_SPEC); 852 if (dayOfMSpec && !dayOfWSpec) { st = daysOfMonth.tailSet(new Integer (day)); 855 if (lastdayOfMonth) { 856 t = day; 857 day = getLastDayOfMonth(mon); 858 } else if (st != null && st.size() != 0) { 859 t = day; 860 day = ((Integer ) st.first()).intValue(); 861 } else { 862 day = ((Integer ) daysOfMonth.first()).intValue(); 863 mon++; 864 } 865 if (day != t) { 866 cl.set(Calendar.SECOND, 0); 867 cl.set(Calendar.MINUTE, 0); 868 cl.set(Calendar.HOUR_OF_DAY, 0); 869 cl.set(Calendar.DAY_OF_MONTH, day); 870 cl.set(Calendar.MONTH, mon - 1); |