Index: 3rdParty_sources/quartz/org/quartz/Calendar.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/Calendar.java (.../Calendar.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/Calendar.java (.../Calendar.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,24 +16,29 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ - - package org.quartz; /** - *
- * An interface to be implemented by objects that define spaces of time that
- * should be included or excluded from a {@link Trigger}
's
- * normal 'firing' schedule.
- *
{@link Trigger}
may (not) fire. Calendars
+ * do not define actual fire times, but rather are used to limit a
+ * Trigger
from firing on its normal schedule if necessary. Most
+ * Calendars include all times by default and allow the user to specify times
+ * to exclude.
*
+ * As such, it is often useful to think of Calendars as being used to exclude a block
+ * of time - as opposed to include a block of time. (i.e. the
+ * schedule "fire every five minutes except on Sundays" could be
+ * implemented with a SimpleTrigger
and a
+ * WeeklyCalendar
which excludes Sundays)
Implementations MUST take care of being properly Cloneable
+ * and Serializable
.
* Get the base calendar. Will be null, if not set. *
*/ - public Calendar getBaseCalendar(); + Calendar getBaseCalendar(); /** ** Determine whether the given time (in milliseconds) is 'included' by the * Calendar. *
*/ - public boolean isTimeIncluded(long timeStamp); + boolean isTimeIncluded(long timeStamp); /** ** Determine the next time (in milliseconds) that is 'included' by the * Calendar after the given time. *
*/ - public long getNextIncludedTime(long timeStamp); + long getNextIncludedTime(long timeStamp); /** *@@ -91,7 +96,7 @@ * * @return null if no description was set. */ - public String getDescription(); + String getDescription(); /** *
@@ -100,5 +105,7 @@ * the description has no meaning to Quartz. *
*/ - public void setDescription(String description); + void setDescription(String description); + + Object clone(); } Index: 3rdParty_sources/quartz/org/quartz/CalendarIntervalScheduleBuilder.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/CalendarIntervalScheduleBuilder.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/CalendarIntervalScheduleBuilder.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,339 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import java.util.TimeZone; + +import org.quartz.DateBuilder.IntervalUnit; +import org.quartz.impl.triggers.CalendarIntervalTriggerImpl; +import org.quartz.spi.MutableTrigger; + +/** + *CalendarIntervalScheduleBuilder
is a {@link ScheduleBuilder}
+ * that defines calendar time (day, week, month, year) interval-based
+ * schedules for Trigger
s.
+ *
+ * Quartz provides a builder-style API for constructing scheduling-related
+ * entities via a Domain-Specific Language (DSL). The DSL can best be
+ * utilized through the usage of static imports of the methods on the classes
+ * TriggerBuilder
, JobBuilder
,
+ * DateBuilder
, JobKey
, TriggerKey
+ * and the various ScheduleBuilder
implementations.
Client code can then use the DSL to write code such as this:
+ *+ * JobDetail job = newJob(MyJob.class) + * .withIdentity("myJob") + * .build(); + * + * Trigger trigger = newTrigger() + * .withIdentity(triggerKey("myTrigger", "myTriggerGroup")) + * .withSchedule(withIntervalInDays(3)) + * .startAt(futureDate(10, MINUTES)) + * .build(); + * + * scheduler.scheduleJob(job, trigger); + *+ * + * @see DailyTimeIntervalScheduleBuilder + * @see CronScheduleBuilder + * @see ScheduleBuilder + * @see SimpleScheduleBuilder + * @see TriggerBuilder + */ +public class CalendarIntervalScheduleBuilder extends ScheduleBuilder{ + + private int interval = 1; + private IntervalUnit intervalUnit = IntervalUnit.DAY; + + private int misfireInstruction = CalendarIntervalTrigger.MISFIRE_INSTRUCTION_SMART_POLICY; + private TimeZone timeZone; + private boolean preserveHourOfDayAcrossDaylightSavings; + private boolean skipDayIfHourDoesNotExist; + + protected CalendarIntervalScheduleBuilder() { + } + + /** + * Create a CalendarIntervalScheduleBuilder. + * + * @return the new CalendarIntervalScheduleBuilder + */ + public static CalendarIntervalScheduleBuilder calendarIntervalSchedule() { + return new CalendarIntervalScheduleBuilder(); + } + + /** + * Build the actual Trigger -- NOT intended to be invoked by end users, + * but will rather be invoked by a TriggerBuilder which this + * ScheduleBuilder is given to. + * + * @see TriggerBuilder#withSchedule(ScheduleBuilder) + */ + @Override + public MutableTrigger build() { + + CalendarIntervalTriggerImpl st = new CalendarIntervalTriggerImpl(); + st.setRepeatInterval(interval); + st.setRepeatIntervalUnit(intervalUnit); + st.setMisfireInstruction(misfireInstruction); + st.setTimeZone(timeZone); + st.setPreserveHourOfDayAcrossDaylightSavings(preserveHourOfDayAcrossDaylightSavings); + st.setSkipDayIfHourDoesNotExist(skipDayIfHourDoesNotExist); + + return st; + } + + /** + * Specify the time unit and interval for the Trigger to be produced. + * + * @param timeInterval the interval at which the trigger should repeat. + * @param unit the time unit (IntervalUnit) of the interval. + * @return the updated CalendarIntervalScheduleBuilder + * @see CalendarIntervalTrigger#getRepeatInterval() + * @see CalendarIntervalTrigger#getRepeatIntervalUnit() + */ + public CalendarIntervalScheduleBuilder withInterval(int timeInterval, IntervalUnit unit) { + if(unit == null) + throw new IllegalArgumentException("TimeUnit must be specified."); + validateInterval(timeInterval); + this.interval = timeInterval; + this.intervalUnit = unit; + return this; + } + + /** + * Specify an interval in the IntervalUnit.SECOND that the produced + * Trigger will repeat at. + * + * @param intervalInSeconds the number of seconds at which the trigger should repeat. + * @return the updated CalendarIntervalScheduleBuilder + * @see CalendarIntervalTrigger#getRepeatInterval() + * @see CalendarIntervalTrigger#getRepeatIntervalUnit() + */ + public CalendarIntervalScheduleBuilder withIntervalInSeconds(int intervalInSeconds) { + validateInterval(intervalInSeconds); + this.interval = intervalInSeconds; + this.intervalUnit = IntervalUnit.SECOND; + return this; + } + + /** + * Specify an interval in the IntervalUnit.MINUTE that the produced + * Trigger will repeat at. + * + * @param intervalInMinutes the number of minutes at which the trigger should repeat. + * @return the updated CalendarIntervalScheduleBuilder + * @see CalendarIntervalTrigger#getRepeatInterval() + * @see CalendarIntervalTrigger#getRepeatIntervalUnit() + */ + public CalendarIntervalScheduleBuilder withIntervalInMinutes(int intervalInMinutes) { + validateInterval(intervalInMinutes); + this.interval = intervalInMinutes; + this.intervalUnit = IntervalUnit.MINUTE; + return this; + } + + /** + * Specify an interval in the IntervalUnit.HOUR that the produced + * Trigger will repeat at. + * + * @param intervalInHours the number of hours at which the trigger should repeat. + * @return the updated CalendarIntervalScheduleBuilder + * @see CalendarIntervalTrigger#getRepeatInterval() + * @see CalendarIntervalTrigger#getRepeatIntervalUnit() + */ + public CalendarIntervalScheduleBuilder withIntervalInHours(int intervalInHours) { + validateInterval(intervalInHours); + this.interval = intervalInHours; + this.intervalUnit = IntervalUnit.HOUR; + return this; + } + + /** + * Specify an interval in the IntervalUnit.DAY that the produced + * Trigger will repeat at. + * + * @param intervalInDays the number of days at which the trigger should repeat. + * @return the updated CalendarIntervalScheduleBuilder + * @see CalendarIntervalTrigger#getRepeatInterval() + * @see CalendarIntervalTrigger#getRepeatIntervalUnit() + */ + public CalendarIntervalScheduleBuilder withIntervalInDays(int intervalInDays) { + validateInterval(intervalInDays); + this.interval = intervalInDays; + this.intervalUnit = IntervalUnit.DAY; + return this; + } + + /** + * Specify an interval in the IntervalUnit.WEEK that the produced + * Trigger will repeat at. + * + * @param intervalInWeeks the number of weeks at which the trigger should repeat. + * @return the updated CalendarIntervalScheduleBuilder + * @see CalendarIntervalTrigger#getRepeatInterval() + * @see CalendarIntervalTrigger#getRepeatIntervalUnit() + */ + public CalendarIntervalScheduleBuilder withIntervalInWeeks(int intervalInWeeks) { + validateInterval(intervalInWeeks); + this.interval = intervalInWeeks; + this.intervalUnit = IntervalUnit.WEEK; + return this; + } + + /** + * Specify an interval in the IntervalUnit.MONTH that the produced + * Trigger will repeat at. + * + * @param intervalInMonths the number of months at which the trigger should repeat. + * @return the updated CalendarIntervalScheduleBuilder + * @see CalendarIntervalTrigger#getRepeatInterval() + * @see CalendarIntervalTrigger#getRepeatIntervalUnit() + */ + public CalendarIntervalScheduleBuilder withIntervalInMonths(int intervalInMonths) { + validateInterval(intervalInMonths); + this.interval = intervalInMonths; + this.intervalUnit = IntervalUnit.MONTH; + return this; + } + + /** + * Specify an interval in the IntervalUnit.YEAR that the produced + * Trigger will repeat at. + * + * @param intervalInYears the number of years at which the trigger should repeat. + * @return the updated CalendarIntervalScheduleBuilder + * @see CalendarIntervalTrigger#getRepeatInterval() + * @see CalendarIntervalTrigger#getRepeatIntervalUnit() + */ + public CalendarIntervalScheduleBuilder withIntervalInYears(int intervalInYears) { + validateInterval(intervalInYears); + this.interval = intervalInYears; + this.intervalUnit = IntervalUnit.YEAR; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link Trigger#MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY} instruction. + * + * @return the updated CronScheduleBuilder + * @see Trigger#MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY + */ + public CalendarIntervalScheduleBuilder withMisfireHandlingInstructionIgnoreMisfires() { + misfireInstruction = Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link CalendarIntervalTrigger#MISFIRE_INSTRUCTION_DO_NOTHING} instruction. + * + * @return the updated CalendarIntervalScheduleBuilder + * @see CalendarIntervalTrigger#MISFIRE_INSTRUCTION_DO_NOTHING + */ + public CalendarIntervalScheduleBuilder withMisfireHandlingInstructionDoNothing() { + misfireInstruction = CalendarIntervalTrigger.MISFIRE_INSTRUCTION_DO_NOTHING; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link CalendarIntervalTrigger#MISFIRE_INSTRUCTION_FIRE_ONCE_NOW} instruction. + * + * @return the updated CalendarIntervalScheduleBuilder + * @see CalendarIntervalTrigger#MISFIRE_INSTRUCTION_FIRE_ONCE_NOW + */ + public CalendarIntervalScheduleBuilder withMisfireHandlingInstructionFireAndProceed() { + misfireInstruction = CalendarIntervalTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW; + return this; + } + /** + * The TimeZone
in which to base the schedule. + * + * @param timezone the time-zone for the schedule. + * @return the updated CalendarIntervalScheduleBuilder + * @see CalendarIntervalTrigger#getTimeZone() + */ + public CalendarIntervalScheduleBuilder inTimeZone(TimeZone timezone) { + this.timeZone = timezone; + return this; + } + + /** + * If intervals are a day or greater, this property (set to true) will + * cause the firing of the trigger to always occur at the same time of day, + * (the time of day of the startTime) regardless of daylight saving time + * transitions. Default value is false. + * + *+ * For example, without the property set, your trigger may have a start + * time of 9:00 am on March 1st, and a repeat interval of 2 days. But + * after the daylight saving transition occurs, the trigger may start + * firing at 8:00 am every other day. + *
+ * + *+ * If however, the time of day does not exist on a given day to fire + * (e.g. 2:00 am in the United States on the days of daylight saving + * transition), the trigger will go ahead and fire one hour off on + * that day, and then resume the normal hour on other days. If + * you wish for the trigger to never fire at the "wrong" hour, then + * you should set the property skipDayIfHourDoesNotExist. + *
+ * + * @see #skipDayIfHourDoesNotExist(boolean) + * @see #inTimeZone(TimeZone) + * @see TriggerBuilder#startAt(java.util.Date) + */ + public CalendarIntervalScheduleBuilder preserveHourOfDayAcrossDaylightSavings(boolean preserveHourOfDay) { + this.preserveHourOfDayAcrossDaylightSavings = preserveHourOfDay; + return this; + } + + /** + * If intervals are a day or greater, and + * preserveHourOfDayAcrossDaylightSavings property is set to true, and the + * hour of the day does not exist on a given day for which the trigger + * would fire, the day will be skipped and the trigger advanced a second + * interval if this property is set to true. Defaults to false. + * + *+ * CAUTION! If you enable this property, and your hour of day happens + * to be that of daylight savings transition (e.g. 2:00 am in the United + * States) and the trigger's interval would have had the trigger fire on + * that day, then you may actually completely miss a firing on the day of + * transition if that hour of day does not exist on that day! In such a + * case the next fire time of the trigger will be computed as double (if + * the interval is 2 days, then a span of 4 days between firings will + * occur). + *
+ * + * @see #preserveHourOfDayAcrossDaylightSavings(boolean) + */ + public CalendarIntervalScheduleBuilder skipDayIfHourDoesNotExist(boolean skipDay) { + this.skipDayIfHourDoesNotExist = skipDay; + return this; + } + + private void validateInterval(int timeInterval) { + if(timeInterval <= 0) + throw new IllegalArgumentException("Interval must be a positive value."); + } +} Index: 3rdParty_sources/quartz/org/quartz/CalendarIntervalTrigger.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/CalendarIntervalTrigger.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/CalendarIntervalTrigger.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,159 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import java.util.Calendar; +import java.util.TimeZone; + +import org.quartz.DateBuilder.IntervalUnit; + +/** + * A concrete{@link Trigger}
that is used to fire a{@link org.quartz.JobDetail}
+ * based upon repeating calendar time intervals. + * + *The trigger will fire every N (see {@link #getRepeatInterval()} ) units of calendar time + * (see {@link #getRepeatIntervalUnit()}) as specified in the trigger's definition. + * This trigger can achieve schedules that are not possible with {@link SimpleTrigger} (e.g + * because months are not a fixed number of seconds) or {@link CronTrigger} (e.g. because + * "every 5 months" is not an even divisor of 12).
+ * + *If you use an interval unit of
+ * + * @see TriggerBuilder + * @see CalendarIntervalScheduleBuilder + * @see SimpleScheduleBuilder + * @see CronScheduleBuilder + * + * @author James House + */ +public interface CalendarIntervalTrigger extends Trigger { + + /** + *MONTH
then care should be taken when setting + * astartTime
value that is on a day near the end of the month. For example, + * if you choose a start time that occurs on January 31st, and have a trigger with unit + *MONTH
and interval1
, then the next fire time will be February 28th, + * and the next time after that will be March 28th - and essentially each subsequent firing will + * occur on the 28th of the month, even if a 31st day exists. If you want a trigger that always + * fires on the last day of the month - regardless of the number of days in the month, + * you should useCronTrigger
.+ * Instructs the
+ */ + public static final int MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1; + /** + *{@link Scheduler}
that upon a mis-fire + * situation, the{@link CalendarIntervalTrigger}
wants to be + * fired now byScheduler
. + *+ * Instructs the
+ */ + public static final int MISFIRE_INSTRUCTION_DO_NOTHING = 2; + + /** + *{@link Scheduler}
that upon a mis-fire + * situation, the{@link CalendarIntervalTrigger}
wants to have it's + * next-fire-time updated to the next time in the schedule after the + * current time (taking into account any associated{@link Calendar}
, + * but it does not want to be fired now. + *Get the interval unit - the time unit on with the interval applies.
+ */ + public IntervalUnit getRepeatIntervalUnit(); + + /** + *+ * Get the the time interval that will be added to the
+ */ + public int getRepeatInterval(); + + /** + *DateIntervalTrigger
's + * fire time (in the set repeat interval unit) in order to calculate the time of the + * next trigger repeat. + *+ * Get the number of times the
+ */ + public int getTimesTriggered(); + + /** + *DateIntervalTrigger
has already + * fired. + *+ * Gets the time zone within which time calculations related to this + * trigger will be performed. + *
+ * + *+ * If null, the system default TimeZone will be used. + *
+ */ + public TimeZone getTimeZone(); + + + /** + * If intervals are a day or greater, this property (set to true) will + * cause the firing of the trigger to always occur at the same time of day, + * (the time of day of the startTime) regardless of daylight saving time + * transitions. Default value is false. + * + *+ * For example, without the property set, your trigger may have a start + * time of 9:00 am on March 1st, and a repeat interval of 2 days. But + * after the daylight saving transition occurs, the trigger may start + * firing at 8:00 am every other day. + *
+ * + *+ * If however, the time of day does not exist on a given day to fire + * (e.g. 2:00 am in the United States on the days of daylight saving + * transition), the trigger will go ahead and fire one hour off on + * that day, and then resume the normal hour on other days. If + * you wish for the trigger to never fire at the "wrong" hour, then + * you should set the property skipDayIfHourDoesNotExist. + *
+ * + * @see #isSkipDayIfHourDoesNotExist() + * @see #getStartTime() + * @see #getTimeZone() + */ + public boolean isPreserveHourOfDayAcrossDaylightSavings(); + + /** + * If intervals are a day or greater, and + * preserveHourOfDayAcrossDaylightSavings property is set to true, and the + * hour of the day does not exist on a given day for which the trigger + * would fire, the day will be skipped and the trigger advanced a second + * interval if this property is set to true. Defaults to false. + * + *+ * CAUTION! If you enable this property, and your hour of day happens + * to be that of daylight savings transition (e.g. 2:00 am in the United + * States) and the trigger's interval would have had the trigger fire on + * that day, then you may actually completely miss a firing on the day of + * transition if that hour of day does not exist on that day! In such a + * case the next fire time of the trigger will be computed as double (if + * the interval is 2 days, then a span of 4 days between firings will + * occur). + *
+ * + * @see #isPreserveHourOfDayAcrossDaylightSavings() + */ + public boolean isSkipDayIfHourDoesNotExist(); + + + TriggerBuildergetTriggerBuilder(); +} Fisheye: Tag c208628989d52041b3765784f4c8cbfd6c80d47b refers to a dead (removed) revision in file `3rdParty_sources/quartz/org/quartz/CriticalSchedulerException.java'. Fisheye: No comparison available. Pass `N' to diff? Index: 3rdParty_sources/quartz/org/quartz/CronExpression.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/CronExpression.java (.../CronExpression.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/CronExpression.java (.../CronExpression.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,3 +1,20 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + package org.quartz; import java.io.Serializable; @@ -56,7 +73,7 @@ * * * 1-31
- * + * , - * ? / L W C
* * , - * ? / L W
* @@ -75,7 +92,7 @@ * Month
* @@ -86,7 +103,7 @@ ** Year (Optional)
- * + * empty, 1970-2099
* empty, 1970-2199
* * , - * /
* The '?' character is allowed for the day-of-month and day-of-week fields. It * is used to specify 'no specific value'. This is useful when you need to - * specify something in one of the two fileds, but not the other. + * specify something in one of the two fields, but not the other. *
* The '-' character is used to specify ranges For example "10-12" in * the hour field means "the hours 10, 11 and 12". @@ -115,9 +132,10 @@ * day-of-week field by itself, it simply means "7" or * "SAT". But if used in the day-of-week field after another value, it * means "the last xxx day of the month" - for example "6L" - * means "the last friday of the month". When using the 'L' option, it - * is important not to specify lists, or ranges of values, as you'll get - * confusing results. + * means "the last friday of the month". You can also specify an offset + * from the last day of the month, such as "L-3" which would mean the third-to-last + * day of the calendar month. When using the 'L' option, it is important not to + * specify lists, or ranges of values, as you'll get confusing/unexpected results. *
* The 'W' character is allowed for the day-of-month field. This character * is used to specify the weekday (Monday-Friday) nearest the given day. As an @@ -142,15 +160,17 @@ * Other examples: "2#1" = the first Monday of the month and * "4#5" = the fifth Wednesday of the month. Note that if you specify * "#5" and there is not 5 of the given day-of-week in the month, then - * no firing will occur that month. + * no firing will occur that month. If the '#' character is used, there can + * only be one expression in the day-of-week field ("3#1,6#3" is + * not valid, since there are two expressions). *
* + * means "the first day included by the calendar on or after Sunday".--> *
* The legal characters and the names of months and days of the week are not * case sensitive. @@ -159,8 +179,15 @@ * NOTES: *
*
* * @@ -169,11 +196,11 @@ * @author Contributions from Mads Henderson * @author Refactoring from CronTrigger to CronExpression by Aaron Craven */ -public class CronExpression implements Serializable, Cloneable { +public final class CronExpression implements Serializable, Cloneable { - private static final long serialVersionUID = 12423409423L; - - protected static final int SECOND = 0; + private static final long serialVersionUID = 12423409423L; + + protected static final int SECOND = 0; protected static final int MINUTE = 1; protected static final int HOUR = 2; protected static final int DAY_OF_MONTH = 3; @@ -182,158 +209,225 @@ protected static final int YEAR = 6; protected static final int ALL_SPEC_INT = 99; // '*' protected static final int NO_SPEC_INT = 98; // '?' - protected static final Integer ALL_SPEC = new Integer(ALL_SPEC_INT); - protected static final Integer NO_SPEC = new Integer(NO_SPEC_INT); + protected static final Integer ALL_SPEC = ALL_SPEC_INT; + protected static final Integer NO_SPEC = NO_SPEC_INT; - protected static Map monthMap = new HashMap(20); - protected static Map dayMap = new HashMap(60); + protected static final Map- Support for specifying both a day-of-week and a day-of-month value is - * not complete (you'll need to use the '?' character in on of these fields). + * not complete (you'll need to use the '?' character in one of these fields). *
+ *- Overflowing ranges is supported - that is, having a larger number on + * the left hand side than the right. You might do 22-2 to catch 10 o'clock + * at night until 2 o'clock in the morning, or you might have NOV-FEB. It is + * very important to note that overuse of overflowing ranges creates ranges + * that don't make sense and no effort has been made to determine which + * interpretation CronExpression chooses. An example would be + * "0 0 14-6 ? * FRI-MON".
*monthMap = new HashMap (20); + protected static final Map dayMap = new HashMap (60); static { - monthMap.put("JAN", new Integer(0)); - monthMap.put("FEB", new Integer(1)); - monthMap.put("MAR", new Integer(2)); - monthMap.put("APR", new Integer(3)); - monthMap.put("MAY", new Integer(4)); - monthMap.put("JUN", new Integer(5)); - monthMap.put("JUL", new Integer(6)); - monthMap.put("AUG", new Integer(7)); - monthMap.put("SEP", new Integer(8)); - monthMap.put("OCT", new Integer(9)); - monthMap.put("NOV", new Integer(10)); - monthMap.put("DEC", new Integer(11)); + monthMap.put("JAN", 0); + monthMap.put("FEB", 1); + monthMap.put("MAR", 2); + monthMap.put("APR", 3); + monthMap.put("MAY", 4); + monthMap.put("JUN", 5); + monthMap.put("JUL", 6); + monthMap.put("AUG", 7); + monthMap.put("SEP", 8); + monthMap.put("OCT", 9); + monthMap.put("NOV", 10); + monthMap.put("DEC", 11); - dayMap.put("SUN", new Integer(1)); - dayMap.put("MON", new Integer(2)); - dayMap.put("TUE", new Integer(3)); - dayMap.put("WED", new Integer(4)); - dayMap.put("THU", new Integer(5)); - dayMap.put("FRI", new Integer(6)); - dayMap.put("SAT", new Integer(7)); + dayMap.put("SUN", 1); + dayMap.put("MON", 2); + dayMap.put("TUE", 3); + dayMap.put("WED", 4); + dayMap.put("THU", 5); + dayMap.put("FRI", 6); + dayMap.put("SAT", 7); } - private String cronExpression = null; + private final String cronExpression; private TimeZone timeZone = null; - protected transient TreeSet seconds; - protected transient TreeSet minutes; - protected transient TreeSet hours; - protected transient TreeSet daysOfMonth; - protected transient TreeSet months; - protected transient TreeSet daysOfWeek; - protected transient TreeSet years; + protected transient TreeSet seconds; + protected transient TreeSet minutes; + protected transient TreeSet hours; + protected transient TreeSet daysOfMonth; + protected transient TreeSet months; + protected transient TreeSet daysOfWeek; + protected transient TreeSet years; protected transient boolean lastdayOfWeek = false; protected transient int nthdayOfWeek = 0; protected transient boolean lastdayOfMonth = false; protected transient boolean nearestWeekday = false; - protected transient boolean calendardayOfWeek = false; - protected transient boolean calendardayOfMonth = false; + protected transient int lastdayOffset = 0; protected transient boolean expressionParsed = false; - + + public static final int MAX_YEAR = Calendar.getInstance().get(Calendar.YEAR) + 100; + /** - * Constructs a new CronExpression
based on the specified - * parameter. - * - * @param cronExpression String representation of the cron expression the - * new object should represent - * @throws java.text.ParseException - * if the string expression cannot be parsed into a valid - *CronExpression
- */ - public CronExpression(String cronExpression) throws ParseException { - if (cronExpression == null) { - throw new IllegalArgumentException("cronExpression cannot be null"); - } - - this.cronExpression = cronExpression; - - buildExpression(cronExpression.toUpperCase(Locale.US)); - } - - /** - * Indicates whether the given date satisfies the cron expression. Note that - * milliseconds are ignored, so two Dates falling on different milliseconds - * of the same second will always have the same result here. - * - * @param date the date to evaluate - * @return a boolean indicating whether the given date satisfies the cron - * expression - */ - public boolean isSatisfiedBy(Date date) { - Calendar testDateCal = Calendar.getInstance(); - testDateCal.setTime(date); - testDateCal.set(Calendar.MILLISECOND, 0); - Date originalDate = testDateCal.getTime(); - - testDateCal.add(Calendar.SECOND, -1); - - if (getTimeAfter(testDateCal.getTime()).equals(originalDate)) { - return true; - } else { - return false; - } - } - - /** - * Returns the next date/time after the given date/time which - * satisfies the cron expression. - * - * @param date the date/time at which to begin the search for the next valid - * date/time - * @return the next valid date/time - */ - public Date getNextValidTimeAfter(Date date) { - return getTimeAfter(date); - } - + * Constructs a newCronExpression
based on the specified + * parameter. + * + * @param cronExpression String representation of the cron expression the + * new object should represent + * @throws java.text.ParseException + * if the string expression cannot be parsed into a valid + *CronExpression
+ */ + public CronExpression(String cronExpression) throws ParseException { + if (cronExpression == null) { + throw new IllegalArgumentException("cronExpression cannot be null"); + } + + this.cronExpression = cronExpression.toUpperCase(Locale.US); + + buildExpression(this.cronExpression); + } + /** - *- * Returns the time zone for which the
+ * Constructs a new {@code CronExpression} as a copy of an existing + * instance. + * + * @param expression + * The existing cron expression to be copied */ + public CronExpression(CronExpression expression) { + /* + * We don't call the other constructor here since we need to swallow the + * ParseException. We also elide some of the sanity checking as it is + * not logically trippable. + */ + this.cronExpression = expression.getCronExpression(); + try { + buildExpression(cronExpression); + } catch (ParseException ex) { + throw new AssertionError(); + } + if (expression.getTimeZone() != null) { + setTimeZone((TimeZone) expression.getTimeZone().clone()); + } + } + + /** + * Indicates whether the given date satisfies the cron expression. Note that + * milliseconds are ignored, so two Dates falling on different milliseconds + * of the same second will always have the same result here. + * + * @param date the date to evaluate + * @return a boolean indicating whether the given date satisfies the cron + * expression + */ + public boolean isSatisfiedBy(Date date) { + Calendar testDateCal = Calendar.getInstance(getTimeZone()); + testDateCal.setTime(date); + testDateCal.set(Calendar.MILLISECOND, 0); + Date originalDate = testDateCal.getTime(); + + testDateCal.add(Calendar.SECOND, -1); + + Date timeAfter = getTimeAfter(testDateCal.getTime()); + + return ((timeAfter != null) && (timeAfter.equals(originalDate))); + } + + /** + * Returns the next date/time after the given date/time which + * satisfies the cron expression. + * + * @param date the date/time at which to begin the search for the next valid + * date/time + * @return the next valid date/time + */ + public Date getNextValidTimeAfter(Date date) { + return getTimeAfter(date); + } + + /** + * Returns the next date/time after the given date/time which does + * not satisfy the expression + * + * @param date the date/time at which to begin the search for the next + * invalid date/time + * @return the next valid date/time + */ + public Date getNextInvalidTimeAfter(Date date) { + long difference = 1000; + + //move back to the nearest second so differences will be accurate + Calendar adjustCal = Calendar.getInstance(getTimeZone()); + adjustCal.setTime(date); + adjustCal.set(Calendar.MILLISECOND, 0); + Date lastDate = adjustCal.getTime(); + + Date newDate; + + //FUTURE_TODO: (QUARTZ-481) IMPROVE THIS! The following is a BAD solution to this problem. Performance will be very bad here, depending on the cron expression. It is, however A solution. + + //keep getting the next included time until it's farther than one second + // apart. At that point, lastDate is the last valid fire time. We return + // the second immediately following it. + while (difference == 1000) { + newDate = getTimeAfter(lastDate); + if(newDate == null) + break; + + difference = newDate.getTime() - lastDate.getTime(); + + if (difference == 1000) { + lastDate = newDate; + } + } + + return new Date(lastDate.getTime() + 1000); + } + + /** + * Returns the time zone for which thiscronExpression
of - * thisCronTrigger
will be resolved. - *CronExpression
+ * will be resolved. + */ public TimeZone getTimeZone() { - if (timeZone == null) timeZone = TimeZone.getDefault(); + if (timeZone == null) { + timeZone = TimeZone.getDefault(); + } return timeZone; } /** - *- * Sets the time zone for which the
+ * Sets the time zone for which thiscronExpression
of this - *CronTrigger
will be resolved. - *CronExpression
+ * will be resolved. */ public void setTimeZone(TimeZone timeZone) { this.timeZone = timeZone; } - - /** - * Returns the string representation of theCronExpression
- * - * @return a string representation of theCronExpression
- */ - public String toString() { - return cronExpression; - } - - /** - * Indicates whether the specified cron expression can be parsed into a - * valid cron expression - * - * @param cronExpression the expression to evaluate - * @return a boolean indicating whether the given expression is a valid cron - * expression - */ - public static boolean isValidExpression(String cronExpression) { - - try { - new CronExpression(cronExpression); - } catch (ParseException pe) { - return false; - } - - return true; - } - + + /** + * Returns the string representation of theCronExpression
+ * + * @return a string representation of theCronExpression
+ */ + @Override + public String toString() { + return cronExpression; + } + + /** + * Indicates whether the specified cron expression can be parsed into a + * valid cron expression + * + * @param cronExpression the expression to evaluate + * @return a boolean indicating whether the given expression is a valid cron + * expression + */ + public static boolean isValidExpression(String cronExpression) { + + try { + new CronExpression(cronExpression); + } catch (ParseException pe) { + return false; + } + + return true; + } + + public static void validateExpression(String cronExpression) throws ParseException { + + new CronExpression(cronExpression); + } + + //////////////////////////////////////////////////////////////////////////// // // Expression Parsing Functions @@ -345,13 +439,27 @@ try { - if (seconds == null) seconds = new TreeSet(); - if (minutes == null) minutes = new TreeSet(); - if (hours == null) hours = new TreeSet(); - if (daysOfMonth == null) daysOfMonth = new TreeSet(); - if (months == null) months = new TreeSet(); - if (daysOfWeek == null) daysOfWeek = new TreeSet(); - if (years == null) years = new TreeSet(); + if (seconds == null) { + seconds = new TreeSet(); + } + if (minutes == null) { + minutes = new TreeSet (); + } + if (hours == null) { + hours = new TreeSet (); + } + if (daysOfMonth == null) { + daysOfMonth = new TreeSet (); + } + if (months == null) { + months = new TreeSet (); + } + if (daysOfWeek == null) { + daysOfWeek = new TreeSet (); + } + if (years == null) { + years = new TreeSet (); + } int exprOn = SECOND; @@ -360,6 +468,19 @@ while (exprsTok.hasMoreTokens() && exprOn <= YEAR) { String expr = exprsTok.nextToken().trim(); + + // throw an exception if L is used with other days of the month + if(exprOn == DAY_OF_MONTH && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) { + throw new ParseException("Support for specifying 'L' and 'LW' with other days of the month is not implemented", -1); + } + // throw an exception if L is used with other days of the week + if(exprOn == DAY_OF_WEEK && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) { + throw new ParseException("Support for specifying 'L' with other days of the week is not implemented", -1); + } + if(exprOn == DAY_OF_WEEK && expr.indexOf('#') != -1 && expr.indexOf('#', expr.indexOf('#') +1) != -1) { + throw new ParseException("Support for specifying multiple \"nth\" days is not implemented.", -1); + } + StringTokenizer vTok = new StringTokenizer(expr, ","); while (vTok.hasMoreTokens()) { String v = vTok.nextToken(); @@ -369,12 +490,28 @@ exprOn++; } - if (exprOn <= DAY_OF_WEEK) - throw new ParseException("Unexpected end of expression.", + if (exprOn <= DAY_OF_WEEK) { + throw new ParseException("Unexpected end of expression.", expression.length()); + } - if (exprOn <= YEAR) storeExpressionVals(0, "*", YEAR); + if (exprOn <= YEAR) { + storeExpressionVals(0, "*", YEAR); + } + TreeSet dow = getSet(DAY_OF_WEEK); + TreeSet dom = getSet(DAY_OF_MONTH); + + // Copying the logic from the UnsupportedOperationException below + boolean dayOfMSpec = !dom.contains(NO_SPEC); + boolean dayOfWSpec = !dow.contains(NO_SPEC); + + if (!dayOfMSpec || dayOfWSpec) { + if (!dayOfWSpec || dayOfMSpec) { + throw new ParseException( + "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.", 0); + } + } } catch (ParseException pe) { throw pe; } catch (Exception e) { @@ -384,57 +521,58 @@ } protected int storeExpressionVals(int pos, String s, int type) - throws ParseException { + throws ParseException { + int incr = 0; int i = skipWhiteSpace(pos, s); - if (i >= s.length()) return i; + if (i >= s.length()) { + return i; + } char c = s.charAt(i); - if ((c >= 'A') && (c <= 'Z') && (!s.equals("L")) && (!s.equals("LW"))) { + if ((c >= 'A') && (c <= 'Z') && (!s.equals("L")) && (!s.equals("LW")) && (!s.matches("^L-[0-9]*[W]?"))) { String sub = s.substring(i, i + 3); int sval = -1; int eval = -1; if (type == MONTH) { sval = getMonthNumber(sub) + 1; - if (sval < 0) - throw new ParseException("Invalid Month value: '" + sub - + "'", i); + if (sval <= 0) { + throw new ParseException("Invalid Month value: '" + sub + "'", i); + } if (s.length() > i + 3) { c = s.charAt(i + 3); if (c == '-') { i += 4; sub = s.substring(i, i + 3); eval = getMonthNumber(sub) + 1; - if (eval < 0) - throw new ParseException( - "Invalid Month value: '" + sub + "'", i); + if (eval <= 0) { + throw new ParseException("Invalid Month value: '" + sub + "'", i); + } } } } else if (type == DAY_OF_WEEK) { sval = getDayOfWeekNumber(sub); - if (sval < 0) - throw new ParseException("Invalid Day-of-Week value: '" + if (sval < 0) { + throw new ParseException("Invalid Day-of-Week value: '" + sub + "'", i); + } if (s.length() > i + 3) { c = s.charAt(i + 3); if (c == '-') { i += 4; sub = s.substring(i, i + 3); eval = getDayOfWeekNumber(sub); - if (eval < 0) + if (eval < 0) { throw new ParseException( "Invalid Day-of-Week value: '" + sub + "'", i); - if (sval > eval) - throw new ParseException( - "Invalid Day-of-Week sequence: " + sval - + " > " + eval, i); - + } } else if (c == '#') { try { i += 4; nthdayOfWeek = Integer.parseInt(s.substring(i)); - if (nthdayOfWeek < 1 || nthdayOfWeek > 5) - throw new Exception(); + if (nthdayOfWeek < 1 || nthdayOfWeek > 5) { + throw new Exception(); + } } catch (Exception e) { throw new ParseException( "A numeric value between 1 and 5 must follow the '#' option", @@ -451,27 +589,32 @@ "Illegal characters for this position: '" + sub + "'", i); } - if (eval != -1) incr = 1; + if (eval != -1) { + incr = 1; + } addToSet(sval, eval, incr, type); return (i + 3); } if (c == '?') { i++; - if ((i + 1) < s.length() - && (s.charAt(i) != ' ' && s.charAt(i + 1) != '\t')) - throw new ParseException("Illegal character after '?': " + if ((i + 1) < s.length() + && (s.charAt(i) != ' ' && s.charAt(i + 1) != '\t')) { + throw new ParseException("Illegal character after '?': " + s.charAt(i), i); - if (type != DAY_OF_WEEK && type != DAY_OF_MONTH) - throw new ParseException( + } + if (type != DAY_OF_WEEK && type != DAY_OF_MONTH) { + throw new ParseException( "'?' can only be specfied for Day-of-Month or Day-of-Week.", i); + } if (type == DAY_OF_WEEK && !lastdayOfMonth) { - int val = ((Integer) daysOfMonth.last()).intValue(); - if (val == NO_SPEC_INT) - throw new ParseException( + int val = daysOfMonth.last(); + if (val == NO_SPEC_INT) { + throw new ParseException( "'?' can only be specfied for Day-of-Month -OR- Day-of-Week.", i); + } } addToSet(NO_SPEC_INT, -1, 0, type); @@ -484,51 +627,73 @@ return i + 1; } else if (c == '/' && ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s - .charAt(i + 1) == '\t')) throw new ParseException( - "'/' must be followed by an integer.", i); - else if (c == '*') i++; + .charAt(i + 1) == '\t')) { + throw new ParseException("'/' must be followed by an integer.", i); + } else if (c == '*') { + i++; + } c = s.charAt(i); if (c == '/') { // is an increment specified? i++; - if (i >= s.length()) - throw new ParseException("Unexpected end of string.", i); + if (i >= s.length()) { + throw new ParseException("Unexpected end of string.", i); + } incr = getNumericValue(s, i); i++; - if (incr > 10) i++; - if (incr > 59 && (type == SECOND || type == MINUTE)) throw new ParseException( - "Increment > 60 : " + incr, i); - else if (incr > 23 && (type == HOUR)) throw new ParseException( - "Increment > 24 : " + incr, i); - else if (incr > 31 && (type == DAY_OF_MONTH)) throw new ParseException( - "Increment > 31 : " + incr, i); - else if (incr > 7 && (type == DAY_OF_WEEK)) throw new ParseException( - "Increment > 7 : " + incr, i); - else if (incr > 12 && (type == MONTH)) - throw new ParseException("Increment > 12 : " + incr, i); - } else + if (incr > 10) { + i++; + } + if (incr > 59 && (type == SECOND || type == MINUTE)) { + throw new ParseException("Increment > 60 : " + incr, i); + } else if (incr > 23 && (type == HOUR)) { + throw new ParseException("Increment > 24 : " + incr, i); + } else if (incr > 31 && (type == DAY_OF_MONTH)) { + throw new ParseException("Increment > 31 : " + incr, i); + } else if (incr > 7 && (type == DAY_OF_WEEK)) { + throw new ParseException("Increment > 7 : " + incr, i); + } else if (incr > 12 && (type == MONTH)) { + throw new ParseException("Increment > 12 : " + incr, i); + } + } else { incr = 1; + } addToSet(ALL_SPEC_INT, -1, incr, type); return i; } else if (c == 'L') { i++; - if (type == DAY_OF_MONTH) lastdayOfMonth = true; - if (type == DAY_OF_WEEK) addToSet(7, 7, 0, type); + if (type == DAY_OF_MONTH) { + lastdayOfMonth = true; + } + if (type == DAY_OF_WEEK) { + addToSet(7, 7, 0, type); + } if(type == DAY_OF_MONTH && s.length() > i) { c = s.charAt(i); - if(c == 'W') { - nearestWeekday = true; - i++; + if(c == '-') { + ValueSet vs = getValue(0, s, i+1); + lastdayOffset = vs.value; + if(lastdayOffset > 30) + throw new ParseException("Offset from last day must be <= 30", i+1); + i = vs.pos; + } + if(s.length() > i) { + c = s.charAt(i); + if(c == 'W') { + nearestWeekday = true; + i++; + } } } return i; } else if (c >= '0' && c <= '9') { int val = Integer.parseInt(String.valueOf(c)); i++; - if (i >= s.length()) addToSet(val, -1, -1, type); - else { + if (i >= s.length()) { + addToSet(val, -1, -1, type); + } else { c = s.charAt(i); if (c >= '0' && c <= '9') { ValueSet vs = getValue(val, s, i); @@ -538,14 +703,16 @@ i = checkNext(i, s, val, type); return i; } - } else + } else { throw new ParseException("Unexpected character: " + c, i); + } return i; } protected int checkNext(int pos, String s, int val, int type) - throws ParseException { + throws ParseException { + int end = -1; int i = pos; @@ -557,60 +724,55 @@ char c = s.charAt(pos); if (c == 'L') { - if (type == DAY_OF_WEEK) lastdayOfWeek = true; - else - throw new ParseException("'L' option is not valid here. (pos=" - + i + ")", i); - TreeSet set = getSet(type); - set.add(new Integer(val)); + if (type == DAY_OF_WEEK) { + if(val < 1 || val > 7) + throw new ParseException("Day-of-Week values must be between 1 and 7", -1); + lastdayOfWeek = true; + } else { + throw new ParseException("'L' option is not valid here. (pos=" + i + ")", i); + } + TreeSet set = getSet(type); + set.add(val); i++; return i; } if (c == 'W') { - if(type == DAY_OF_MONTH) nearestWeekday = true; - else - throw new ParseException("'W' option is not valid here. (pos=" - + i + ")", i); - TreeSet set = getSet(type); - set.add(new Integer(val)); + if (type == DAY_OF_MONTH) { + nearestWeekday = true; + } else { + throw new ParseException("'W' option is not valid here. (pos=" + i + ")", i); + } + if(val > 31) + throw new ParseException("The 'W' option does not make sense with values larger than 31 (max number of days in a month)", i); + TreeSet set = getSet(type); + set.add(val); i++; return i; } if (c == '#') { - if (type != DAY_OF_WEEK) - throw new ParseException( - "'#' option is not valid here. (pos=" + i + ")", i); + if (type != DAY_OF_WEEK) { + throw new ParseException("'#' option is not valid here. (pos=" + i + ")", i); + } i++; try { nthdayOfWeek = Integer.parseInt(s.substring(i)); - if (nthdayOfWeek < 1 || nthdayOfWeek > 5) - throw new Exception(); + if (nthdayOfWeek < 1 || nthdayOfWeek > 5) { + throw new Exception(); + } } catch (Exception e) { throw new ParseException( "A numeric value between 1 and 5 must follow the '#' option", i); } - TreeSet set = getSet(type); - set.add(new Integer(val)); + TreeSet set = getSet(type); + set.add(val); i++; return i; } - if (c == 'C') { - if (type == DAY_OF_WEEK) calendardayOfWeek = true; - else if (type == DAY_OF_MONTH) calendardayOfMonth = true; - else - throw new ParseException("'C' option is not valid here. (pos=" - + i + ")", i); - TreeSet set = getSet(type); - set.add(new Integer(val)); - i++; - return i; - } - if (c == '-') { i++; c = s.charAt(i); @@ -624,8 +786,7 @@ c = s.charAt(i); if (c >= '0' && c <= '9') { ValueSet vs = getValue(v, s, i); - int v1 = vs.value; - end = v1; + end = vs.value; i = vs.pos; } if (i < s.length() && ((c = s.charAt(i)) == '/')) { @@ -670,9 +831,9 @@ addToSet(val, end, v3, type); i = vs.pos; return i; - } else - throw new ParseException("Unexpected character '" + c - + "' after '/'", i); + } else { + throw new ParseException("Unexpected character '" + c + "' after '/'", i); + } } addToSet(val, end, 0, type); @@ -681,11 +842,11 @@ } public String getCronExpression() { - return cronExpression; + return cronExpression; } public String getExpressionSummary() { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); buf.append("seconds: "); buf.append(getExpressionSetSummary(seconds)); @@ -717,52 +878,58 @@ buf.append("lastdayOfMonth: "); buf.append(lastdayOfMonth); buf.append("\n"); - buf.append("calendardayOfWeek: "); - buf.append(calendardayOfWeek); - buf.append("\n"); - buf.append("calendardayOfMonth: "); - buf.append(calendardayOfMonth); - buf.append("\n"); buf.append("years: "); buf.append(getExpressionSetSummary(years)); buf.append("\n"); return buf.toString(); } - protected String getExpressionSetSummary(java.util.Set set) { + protected String getExpressionSetSummary(java.util.Set set) { - if (set.contains(NO_SPEC)) return "?"; - if (set.contains(ALL_SPEC)) return "*"; + if (set.contains(NO_SPEC)) { + return "?"; + } + if (set.contains(ALL_SPEC)) { + return "*"; + } - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); - Iterator itr = set.iterator(); + Iterator itr = set.iterator(); boolean first = true; while (itr.hasNext()) { - Integer iVal = (Integer) itr.next(); + Integer iVal = itr.next(); String val = iVal.toString(); - if (!first) buf.append(","); + if (!first) { + buf.append(","); + } buf.append(val); first = false; } return buf.toString(); } - protected String getExpressionSetSummary(java.util.ArrayList list) { + protected String getExpressionSetSummary(java.util.ArrayList list) { - if (list.contains(NO_SPEC)) return "?"; - if (list.contains(ALL_SPEC)) return "*"; + if (list.contains(NO_SPEC)) { + return "?"; + } + if (list.contains(ALL_SPEC)) { + return "*"; + } - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); - Iterator itr = list.iterator(); + Iterator itr = list.iterator(); boolean first = true; while (itr.hasNext()) { - Integer iVal = (Integer) itr.next(); + Integer iVal = itr.next(); String val = iVal.toString(); - if (!first) buf.append(","); + if (!first) { + buf.append(","); + } buf.append(val); first = false; } @@ -771,52 +938,63 @@ } protected int skipWhiteSpace(int i, String s) { - for (; i < s.length() && (s.charAt(i) == ' ' || s.charAt(i) == '\t'); i++) + for (; i < s.length() && (s.charAt(i) == ' ' || s.charAt(i) == '\t'); i++) { ; + } return i; } protected int findNextWhiteSpace(int i, String s) { - for (; i < s.length() && (s.charAt(i) != ' ' || s.charAt(i) != '\t'); i++) + for (; i < s.length() && (s.charAt(i) != ' ' || s.charAt(i) != '\t'); i++) { ; + } return i; } protected void addToSet(int val, int end, int incr, int type) - throws ParseException { - TreeSet set = getSet(type); + throws ParseException { + + TreeSet set = getSet(type); if (type == SECOND || type == MINUTE) { - if ((val < 0 || val > 59 || end > 59) && (val != ALL_SPEC_INT)) - throw new ParseException( - "Minute and Second values must be between 0 and 59", - -1); + if ((val < 0 || val > 59 || end > 59) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Minute and Second values must be between 0 and 59", + -1); + } } else if (type == HOUR) { - if ((val < 0 || val > 23 || end > 23) && (val != ALL_SPEC_INT)) - throw new ParseException( - "Hour values must be between 0 and 23", -1); + if ((val < 0 || val > 23 || end > 23) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Hour values must be between 0 and 23", -1); + } } else if (type == DAY_OF_MONTH) { - if ((val < 1 || val > 31 || end > 31) && (val != ALL_SPEC_INT) - && (val != NO_SPEC_INT)) - throw new ParseException( - "Day of month values must be between 1 and 31", -1); + if ((val < 1 || val > 31 || end > 31) && (val != ALL_SPEC_INT) + && (val != NO_SPEC_INT)) { + throw new ParseException( + "Day of month values must be between 1 and 31", -1); + } } else if (type == MONTH) { - if ((val < 1 || val > 12 || end > 12) && (val != ALL_SPEC_INT)) - throw new ParseException( - "Month values must be between 1 and 12", -1); + if ((val < 1 || val > 12 || end > 12) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Month values must be between 1 and 12", -1); + } } else if (type == DAY_OF_WEEK) { if ((val == 0 || val > 7 || end > 7) && (val != ALL_SPEC_INT) - && (val != NO_SPEC_INT)) - throw new ParseException( - "Day-of-Week values must be between 1 and 7", -1); + && (val != NO_SPEC_INT)) { + throw new ParseException( + "Day-of-Week values must be between 1 and 7", -1); + } } if ((incr == 0 || incr == -1) && val != ALL_SPEC_INT) { - if (val != -1) set.add(new Integer(val)); - else + if (val != -1) { + set.add(val); + } else { set.add(NO_SPEC); + } + return; } @@ -829,64 +1007,121 @@ } if (type == SECOND || type == MINUTE) { - if (stopAt == -1) stopAt = 59; - if (startAt == -1 || startAt == ALL_SPEC_INT) startAt = 0; + if (stopAt == -1) { + stopAt = 59; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 0; + } } else if (type == HOUR) { - if (stopAt == -1) stopAt = 23; - if (startAt == -1 || startAt == ALL_SPEC_INT) startAt = 0; + if (stopAt == -1) { + stopAt = 23; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 0; + } } else if (type == DAY_OF_MONTH) { - if (stopAt == -1) stopAt = 31; - if (startAt == -1 || startAt == ALL_SPEC_INT) startAt = 1; + if (stopAt == -1) { + stopAt = 31; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } } else if (type == MONTH) { - if (stopAt == -1) stopAt = 12; - if (startAt == -1 || startAt == ALL_SPEC_INT) startAt = 1; + if (stopAt == -1) { + stopAt = 12; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } } else if (type == DAY_OF_WEEK) { - if (stopAt == -1) stopAt = 7; - if (startAt == -1 || startAt == ALL_SPEC_INT) startAt = 1; + if (stopAt == -1) { + stopAt = 7; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } } else if (type == YEAR) { - if (stopAt == -1) stopAt = 2099; - if (startAt == -1 || startAt == ALL_SPEC_INT) startAt = 1970; + if (stopAt == -1) { + stopAt = MAX_YEAR; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1970; + } } - for (int i = startAt; i <= stopAt; i += incr) - set.add(new Integer(i)); + // if the end of the range is before the start, then we need to overflow into + // the next day, month etc. This is done by adding the maximum amount for that + // type, and using modulus max to determine the value being added. + int max = -1; + if (stopAt < startAt) { + switch (type) { + case SECOND : max = 60; break; + case MINUTE : max = 60; break; + case HOUR : max = 24; break; + case MONTH : max = 12; break; + case DAY_OF_WEEK : max = 7; break; + case DAY_OF_MONTH : max = 31; break; + case YEAR : throw new IllegalArgumentException("Start year must be less than stop year"); + default : throw new IllegalArgumentException("Unexpected type encountered"); + } + stopAt += max; + } + + for (int i = startAt; i <= stopAt; i += incr) { + if (max == -1) { + // ie: there's no max to overflow over + set.add(i); + } else { + // take the modulus to get the real value + int i2 = i % max; + + // 1-indexed ranges should not include 0, and should include their max + if (i2 == 0 && (type == MONTH || type == DAY_OF_WEEK || type == DAY_OF_MONTH) ) { + i2 = max; + } + + set.add(i2); + } + } } - protected TreeSet getSet(int type) { + TreeSet getSet(int type) { switch (type) { - case SECOND: - return seconds; - case MINUTE: - return minutes; - case HOUR: - return hours; - case DAY_OF_MONTH: - return daysOfMonth; - case MONTH: - return months; - case DAY_OF_WEEK: - return daysOfWeek; - case YEAR: - return years; - default: - return null; + case SECOND: + return seconds; + case MINUTE: + return minutes; + case HOUR: + return hours; + case DAY_OF_MONTH: + return daysOfMonth; + case MONTH: + return months; + case DAY_OF_WEEK: + return daysOfWeek; + case YEAR: + return years; + default: + return null; } } protected ValueSet getValue(int v, String s, int i) { char c = s.charAt(i); - String s1 = String.valueOf(v); + StringBuilder s1 = new StringBuilder(String.valueOf(v)); while (c >= '0' && c <= '9') { - s1 += c; + s1.append(c); i++; - if (i >= s.length()) break; + if (i >= s.length()) { + break; + } c = s.charAt(i); } ValueSet val = new ValueSet(); - if (i < s.length()) val.pos = i; - else - val.pos = i + 1; - val.value = Integer.parseInt(s1); + + val.pos = (i < s.length()) ? i : i + 1; + val.value = Integer.parseInt(s1.toString()); return val; } @@ -897,48 +1132,35 @@ } protected int getMonthNumber(String s) { - Integer integer = (Integer) monthMap.get(s); + Integer integer = monthMap.get(s); - if (integer == null) return -1; + if (integer == null) { + return -1; + } - return integer.intValue(); + return integer; } protected int getDayOfWeekNumber(String s) { - Integer integer = (Integer) dayMap.get(s); + Integer integer = dayMap.get(s); - if (integer == null) return -1; + if (integer == null) { + return -1; + } - return integer.intValue(); + return integer; } - protected Date getTime(int sc, int mn, int hr, int dayofmn, int mon) { - try { - Calendar cl = Calendar.getInstance(getTimeZone()); - //cl.add(Calendar.DAY_OF_MONTH,); - if (hr >= 0 && hr <= 12) cl.set(Calendar.AM_PM, Calendar.AM); - if (hr >= 13 && hr <= 23) cl.set(Calendar.AM_PM, Calendar.PM); - cl.setLenient(false); - if (sc != -1) cl.set(Calendar.SECOND, sc); - if (mn != -1) cl.set(Calendar.MINUTE, mn); - if (hr != -1) cl.set(Calendar.HOUR_OF_DAY, hr); - if (dayofmn != -1) cl.set(Calendar.DAY_OF_MONTH, dayofmn); - if (mon != -1) cl.set(Calendar.MONTH, mon); - return cl.getTime(); - } catch (Exception e) { - return null; - } - } - //////////////////////////////////////////////////////////////////////////// // // Computation Functions // //////////////////////////////////////////////////////////////////////////// - protected Date getTimeAfter(Date afterTime) { + public Date getTimeAfter(Date afterTime) { - Calendar cl = Calendar.getInstance(getTimeZone()); + // Computation is based on Gregorian year only. + Calendar cl = new java.util.GregorianCalendar(getTimeZone()); // move ahead one second, since we're computing the time *after* the // given time @@ -952,19 +1174,22 @@ while (!gotOne) { //if (endTime != null && cl.getTime().after(endTime)) return null; + if(cl.get(Calendar.YEAR) > 2999) { // prevent endless loop... + return null; + } - SortedSet st = null; + SortedSet st = null; int t = 0; int sec = cl.get(Calendar.SECOND); int min = cl.get(Calendar.MINUTE); // get second................................................. - st = seconds.tailSet(new Integer(sec)); + st = seconds.tailSet(sec); if (st != null && st.size() != 0) { - sec = ((Integer) st.first()).intValue(); + sec = st.first(); } else { - sec = ((Integer) seconds.first()).intValue(); + sec = seconds.first(); min++; cl.set(Calendar.MINUTE, min); } @@ -975,12 +1200,12 @@ t = -1; // get minute................................................. - st = minutes.tailSet(new Integer(min)); + st = minutes.tailSet(min); if (st != null && st.size() != 0) { t = min; - min = ((Integer) st.first()).intValue(); + min = st.first(); } else { - min = ((Integer) minutes.first()).intValue(); + min = minutes.first(); hr++; } if (min != t) { @@ -996,12 +1221,12 @@ t = -1; // get hour................................................... - st = hours.tailSet(new Integer(hr)); + st = hours.tailSet(hr); if (st != null && st.size() != 0) { t = hr; - hr = ((Integer) st.first()).intValue(); + hr = st.first(); } else { - hr = ((Integer) hours.first()).intValue(); + hr = hours.first(); day++; } if (hr != t) { @@ -1024,17 +1249,27 @@ boolean dayOfMSpec = !daysOfMonth.contains(NO_SPEC); boolean dayOfWSpec = !daysOfWeek.contains(NO_SPEC); if (dayOfMSpec && !dayOfWSpec) { // get day by day of month rule - st = daysOfMonth.tailSet(new Integer(day)); + st = daysOfMonth.tailSet(day); if (lastdayOfMonth) { if(!nearestWeekday) { t = day; day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); - } - else { + day -= lastdayOffset; + if(t > day) { + mon++; + if(mon > 12) { + mon = 1; + tmon = 3333; // ensure test of mon != tmon further below fails + cl.add(Calendar.YEAR, 1); + } + day = 1; + } + } else { t = day; day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + day -= lastdayOffset; - java.util.Calendar tcal = java.util.Calendar.getInstance(); + java.util.Calendar tcal = java.util.Calendar.getInstance(getTimeZone()); tcal.set(Calendar.SECOND, 0); tcal.set(Calendar.MINUTE, 0); tcal.set(Calendar.HOUR_OF_DAY, 0); @@ -1045,14 +1280,15 @@ int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); int dow = tcal.get(Calendar.DAY_OF_WEEK); - if(dow == Calendar.SATURDAY && day == 1) + if(dow == Calendar.SATURDAY && day == 1) { day += 2; - else if(dow == Calendar.SATURDAY) + } else if(dow == Calendar.SATURDAY) { day -= 1; - else if(dow == Calendar.SUNDAY && day == ldom) + } else if(dow == Calendar.SUNDAY && day == ldom) { day -= 2; - else if(dow == Calendar.SUNDAY) + } else if(dow == Calendar.SUNDAY) { day += 1; + } tcal.set(Calendar.SECOND, sec); tcal.set(Calendar.MINUTE, min); @@ -1067,9 +1303,9 @@ } } else if(nearestWeekday) { t = day; - day = ((Integer) daysOfMonth.first()).intValue(); + day = daysOfMonth.first(); - java.util.Calendar tcal = java.util.Calendar.getInstance(); + java.util.Calendar tcal = java.util.Calendar.getInstance(getTimeZone()); tcal.set(Calendar.SECOND, 0); tcal.set(Calendar.MINUTE, 0); tcal.set(Calendar.HOUR_OF_DAY, 0); @@ -1080,14 +1316,15 @@ int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); int dow = tcal.get(Calendar.DAY_OF_WEEK); - if(dow == Calendar.SATURDAY && day == 1) + if(dow == Calendar.SATURDAY && day == 1) { day += 2; - else if(dow == Calendar.SATURDAY) + } else if(dow == Calendar.SATURDAY) { day -= 1; - else if(dow == Calendar.SUNDAY && day == ldom) + } else if(dow == Calendar.SUNDAY && day == ldom) { day -= 2; - else if(dow == Calendar.SUNDAY) + } else if(dow == Calendar.SUNDAY) { day += 1; + } tcal.set(Calendar.SECOND, sec); @@ -1097,15 +1334,20 @@ tcal.set(Calendar.MONTH, mon - 1); Date nTime = tcal.getTime(); if(nTime.before(afterTime)) { - day = ((Integer) daysOfMonth.first()).intValue();; + day = daysOfMonth.first(); mon++; } - } - else if (st != null && st.size() != 0) { + } else if (st != null && st.size() != 0) { t = day; - day = ((Integer) st.first()).intValue(); + day = st.first(); + // make sure we don't over-run a short month, such as february + int lastDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + if (day > lastDay) { + day = daysOfMonth.first(); + mon++; + } } else { - day = ((Integer) daysOfMonth.first()).intValue(); + day = daysOfMonth.first(); mon++; } @@ -1122,12 +1364,16 @@ } else if (dayOfWSpec && !dayOfMSpec) { // get day by day of week rule if (lastdayOfWeek) { // are we looking for the last XXX day of // the month? - int dow = ((Integer) daysOfWeek.first()).intValue(); // desired + int dow = daysOfWeek.first(); // desired // d-o-w int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w int daysToAdd = 0; - if (cDow < dow) daysToAdd = dow - cDow; - if (cDow > dow) daysToAdd = dow + (7 - cDow); + if (cDow < dow) { + daysToAdd = dow - cDow; + } + if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); @@ -1142,9 +1388,10 @@ continue; } - // find date of last occurance of this day in this month... - while ((day + daysToAdd + 7) <= lDay) + // find date of last occurrence of this day in this month... + while ((day + daysToAdd + 7) <= lDay) { daysToAdd += 7; + } day += daysToAdd; @@ -1160,19 +1407,26 @@ } else if (nthdayOfWeek != 0) { // are we looking for the Nth XXX day in the month? - int dow = ((Integer) daysOfWeek.first()).intValue(); // desired + int dow = daysOfWeek.first(); // desired // d-o-w int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w int daysToAdd = 0; - if (cDow < dow) daysToAdd = dow - cDow; - else if (cDow > dow) daysToAdd = dow + (7 - cDow); + if (cDow < dow) { + daysToAdd = dow - cDow; + } else if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } boolean dayShifted = false; - if (daysToAdd > 0) dayShifted = true; + if (daysToAdd > 0) { + dayShifted = true; + } day += daysToAdd; int weekOfMonth = day / 7; - if (day % 7 > 0) weekOfMonth++; + if (day % 7 > 0) { + weekOfMonth++; + } daysToAdd = (nthdayOfWeek - weekOfMonth) * 7; day += daysToAdd; @@ -1197,16 +1451,20 @@ } } else { int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w - int dow = ((Integer) daysOfWeek.first()).intValue(); // desired + int dow = daysOfWeek.first(); // desired // d-o-w - st = daysOfWeek.tailSet(new Integer(cDow)); + st = daysOfWeek.tailSet(cDow); if (st != null && st.size() > 0) { - dow = ((Integer) st.first()).intValue(); + dow = st.first(); } int daysToAdd = 0; - if (cDow < dow) daysToAdd = dow - cDow; - if (cDow > dow) daysToAdd = dow + (7 - cDow); + if (cDow < dow) { + daysToAdd = dow - cDow; + } + if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); @@ -1233,7 +1491,6 @@ } else { // dayOfWSpec && !dayOfMSpec throw new UnsupportedOperationException( "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented."); - // TODO: } cl.set(Calendar.DAY_OF_MONTH, day); @@ -1245,15 +1502,17 @@ // test for expressions that never generate a valid fire date, // but keep looping... - if (year > 2099) return null; + if (year > MAX_YEAR) { + return null; + } // get month................................................... - st = months.tailSet(new Integer(mon)); + st = months.tailSet(mon); if (st != null && st.size() != 0) { t = mon; - mon = ((Integer) st.first()).intValue(); + mon = st.first(); } else { - mon = ((Integer) months.first()).intValue(); + mon = months.first(); year++; } if (mon != t) { @@ -1275,12 +1534,13 @@ t = -1; // get year................................................... - st = years.tailSet(new Integer(year)); + st = years.tailSet(year); if (st != null && st.size() != 0) { t = year; - year = ((Integer) st.first()).intValue(); - } else + year = st.first(); + } else { return null; // ran out of years... + } if (year != t) { cl.set(Calendar.SECOND, 0); @@ -1305,8 +1565,8 @@ * Advance the calendar to the particular hour paying particular attention * to daylight saving problems. * - * @param cal - * @param hour + * @param cal the calendar to operate on + * @param hour the hour to set */ protected void setCalendarHour(Calendar cal, int hour) { cal.set(java.util.Calendar.HOUR_OF_DAY, hour); @@ -1315,74 +1575,81 @@ } } - protected Date getTimeBefore(Date endTime) // TODO: implement - { + /** + * NOT YET IMPLEMENTED: Returns the time before the given time + * that the CronExpression
matches. + */ + public Date getTimeBefore(Date endTime) { + // FUTURE_TODO: implement QUARTZ-423 return null; } + /** + * NOT YET IMPLEMENTED: Returns the final time that the + *CronExpression
will match. + */ + public Date getFinalFireTime() { + // FUTURE_TODO: implement QUARTZ-423 + return null; + } + protected boolean isLeapYear(int year) { - if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) return true; - else - return false; + return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)); } protected int getLastDayOfMonth(int monthNum, int year) { switch (monthNum) { - case 1: - return 31; - case 2: - return (isLeapYear(year)) ? 29 : 28; - case 3: - return 31; - case 4: - return 30; - case 5: - return 31; - case 6: - return 30; - case 7: - return 31; - case 8: - return 31; - case 9: - return 30; - case 10: - return 31; - case 11: - return 30; - case 12: - return 31; - default: - throw new IllegalArgumentException("Illegal month number: " - + monthNum); + case 1: + return 31; + case 2: + return (isLeapYear(year)) ? 29 : 28; + case 3: + return 31; + case 4: + return 30; + case 5: + return 31; + case 6: + return 30; + case 7: + return 31; + case 8: + return 31; + case 9: + return 30; + case 10: + return 31; + case 11: + return 30; + case 12: + return 31; + default: + throw new IllegalArgumentException("Illegal month number: " + + monthNum); } } private void readObject(java.io.ObjectInputStream stream) - throws java.io.IOException, ClassNotFoundException { + throws java.io.IOException, ClassNotFoundException { + stream.defaultReadObject(); try { buildExpression(cronExpression); } catch (Exception ignore) { } // never happens } + @Override + @Deprecated public Object clone() { - CronExpression copy = null; - try { - copy = new CronExpression(getCronExpression()); - copy.setTimeZone(getTimeZone()); - } catch (ParseException ex) { // never happens since the source is valid... - throw new IncompatibleClassChangeError("Not Cloneable."); - } - return copy; - } + return new CronExpression(this); + } } class ValueSet { public int value; public int pos; -} \ No newline at end of file +} Index: 3rdParty_sources/quartz/org/quartz/CronScheduleBuilder.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/CronScheduleBuilder.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/CronScheduleBuilder.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,328 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import java.text.ParseException; +import java.util.TimeZone; + +import org.quartz.impl.triggers.CronTriggerImpl; +import org.quartz.spi.MutableTrigger; + +/** + *CronScheduleBuilder
is a {@link ScheduleBuilder} that defines + * {@link CronExpression}-based schedules forTrigger
s. + * + *+ * Quartz provides a builder-style API for constructing scheduling-related + * entities via a Domain-Specific Language (DSL). The DSL can best be utilized + * through the usage of static imports of the methods on the classes + *
+ * + *TriggerBuilder
,JobBuilder
, + *DateBuilder
,JobKey
,TriggerKey
and + * the variousScheduleBuilder
implementations. + *+ * Client code can then use the DSL to write code such as this: + *
+ * + *+ * JobDetail job = newJob(MyJob.class).withIdentity("myJob").build(); + * + * Trigger trigger = newTrigger() + * .withIdentity(triggerKey("myTrigger", "myTriggerGroup")) + * .withSchedule(dailyAtHourAndMinute(10, 0)) + * .startAt(futureDate(10, MINUTES)).build(); + * + * scheduler.scheduleJob(job, trigger); + * + *+ * + * @see CronExpression + * @see CronTrigger + * @see ScheduleBuilder + * @see SimpleScheduleBuilder + * @see CalendarIntervalScheduleBuilder + * @see TriggerBuilder + */ +public class CronScheduleBuilder extends ScheduleBuilder{ + + private CronExpression cronExpression; + private int misfireInstruction = CronTrigger.MISFIRE_INSTRUCTION_SMART_POLICY; + + protected CronScheduleBuilder(CronExpression cronExpression) { + if (cronExpression == null) { + throw new NullPointerException("cronExpression cannot be null"); + } + this.cronExpression = cronExpression; + } + + /** + * Build the actual Trigger -- NOT intended to be invoked by end users, but + * will rather be invoked by a TriggerBuilder which this ScheduleBuilder is + * given to. + * + * @see TriggerBuilder#withSchedule(ScheduleBuilder) + */ + @Override + public MutableTrigger build() { + + CronTriggerImpl ct = new CronTriggerImpl(); + + ct.setCronExpression(cronExpression); + ct.setTimeZone(cronExpression.getTimeZone()); + ct.setMisfireInstruction(misfireInstruction); + + return ct; + } + + /** + * Create a CronScheduleBuilder with the given cron-expression string - + * which is presumed to b e valid cron expression (and hence only a + * RuntimeException will be thrown if it is not). + * + * @param cronExpression + * the cron expression string to base the schedule on. + * @return the new CronScheduleBuilder + * @throws RuntimeException + * wrapping a ParseException if the expression is invalid + * @see CronExpression + */ + public static CronScheduleBuilder cronSchedule(String cronExpression) { + try { + return cronSchedule(new CronExpression(cronExpression)); + } catch (ParseException e) { + // all methods of construction ensure the expression is valid by + // this point... + throw new RuntimeException("CronExpression '" + cronExpression + + "' is invalid.", e); + } + } + + /** + * Create a CronScheduleBuilder with the given cron-expression string - + * which may not be a valid cron expression (and hence a ParseException will + * be thrown if it is not). + * + * @param cronExpression + * the cron expression string to base the schedule on. + * @return the new CronScheduleBuilder + * @throws ParseException + * if the expression is invalid + * @see CronExpression + */ + public static CronScheduleBuilder cronScheduleNonvalidatedExpression( + String cronExpression) throws ParseException { + return cronSchedule(new CronExpression(cronExpression)); + } + + private static CronScheduleBuilder cronScheduleNoParseException( + String presumedValidCronExpression) { + try { + return cronSchedule(new CronExpression(presumedValidCronExpression)); + } catch (ParseException e) { + // all methods of construction ensure the expression is valid by + // this point... + throw new RuntimeException( + "CronExpression '" + + presumedValidCronExpression + + "' is invalid, which should not be possible, please report bug to Quartz developers.", + e); + } + } + + /** + * Create a CronScheduleBuilder with the given cron-expression. + * + * @param cronExpression + * the cron expression to base the schedule on. + * @return the new CronScheduleBuilder + * @see CronExpression + */ + public static CronScheduleBuilder cronSchedule(CronExpression cronExpression) { + return new CronScheduleBuilder(cronExpression); + } + + /** + * Create a CronScheduleBuilder with a cron-expression that sets the + * schedule to fire every day at the given time (hour and minute). + * + * @param hour + * the hour of day to fire + * @param minute + * the minute of the given hour to fire + * @return the new CronScheduleBuilder + * @see CronExpression + */ + public static CronScheduleBuilder dailyAtHourAndMinute(int hour, int minute) { + DateBuilder.validateHour(hour); + DateBuilder.validateMinute(minute); + + String cronExpression = String.format("0 %d %d ? * *", minute, hour); + + return cronScheduleNoParseException(cronExpression); + } + + /** + * Create a CronScheduleBuilder with a cron-expression that sets the + * schedule to fire at the given day at the given time (hour and minute) on + * the given days of the week. + * + * @param daysOfWeek + * the dasy of the week to fire + * @param hour + * the hour of day to fire + * @param minute + * the minute of the given hour to fire + * @return the new CronScheduleBuilder + * @see CronExpression + * @see DateBuilder#MONDAY + * @see DateBuilder#TUESDAY + * @see DateBuilder#WEDNESDAY + * @see DateBuilder#THURSDAY + * @see DateBuilder#FRIDAY + * @see DateBuilder#SATURDAY + * @see DateBuilder#SUNDAY + */ + + public static CronScheduleBuilder atHourAndMinuteOnGivenDaysOfWeek( + int hour, int minute, Integer... daysOfWeek) { + if (daysOfWeek == null || daysOfWeek.length == 0) + throw new IllegalArgumentException( + "You must specify at least one day of week."); + for (int dayOfWeek : daysOfWeek) + DateBuilder.validateDayOfWeek(dayOfWeek); + DateBuilder.validateHour(hour); + DateBuilder.validateMinute(minute); + + String cronExpression = String.format("0 %d %d ? * %d", minute, hour, + daysOfWeek[0]); + + for (int i = 1; i < daysOfWeek.length; i++) + cronExpression = cronExpression + "," + daysOfWeek[i]; + + return cronScheduleNoParseException(cronExpression); + } + + /** + * Create a CronScheduleBuilder with a cron-expression that sets the + * schedule to fire one per week on the given day at the given time (hour + * and minute). + * + * @param dayOfWeek + * the day of the week to fire + * @param hour + * the hour of day to fire + * @param minute + * the minute of the given hour to fire + * @return the new CronScheduleBuilder + * @see CronExpression + * @see DateBuilder#MONDAY + * @see DateBuilder#TUESDAY + * @see DateBuilder#WEDNESDAY + * @see DateBuilder#THURSDAY + * @see DateBuilder#FRIDAY + * @see DateBuilder#SATURDAY + * @see DateBuilder#SUNDAY + */ + public static CronScheduleBuilder weeklyOnDayAndHourAndMinute( + int dayOfWeek, int hour, int minute) { + DateBuilder.validateDayOfWeek(dayOfWeek); + DateBuilder.validateHour(hour); + DateBuilder.validateMinute(minute); + + String cronExpression = String.format("0 %d %d ? * %d", minute, hour, + dayOfWeek); + + return cronScheduleNoParseException(cronExpression); + } + + /** + * Create a CronScheduleBuilder with a cron-expression that sets the + * schedule to fire one per month on the given day of month at the given + * time (hour and minute). + * + * @param dayOfMonth + * the day of the month to fire + * @param hour + * the hour of day to fire + * @param minute + * the minute of the given hour to fire + * @return the new CronScheduleBuilder + * @see CronExpression + */ + public static CronScheduleBuilder monthlyOnDayAndHourAndMinute( + int dayOfMonth, int hour, int minute) { + DateBuilder.validateDayOfMonth(dayOfMonth); + DateBuilder.validateHour(hour); + DateBuilder.validateMinute(minute); + + String cronExpression = String.format("0 %d %d %d * ?", minute, hour, + dayOfMonth); + + return cronScheduleNoParseException(cronExpression); + } + + /** + * The TimeZone
in which to base the schedule. + * + * @param timezone + * the time-zone for the schedule. + * @return the updated CronScheduleBuilder + * @see CronExpression#getTimeZone() + */ + public CronScheduleBuilder inTimeZone(TimeZone timezone) { + cronExpression.setTimeZone(timezone); + return this; + } + + /** + * If the Trigger misfires, use the + * {@link Trigger#MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY} instruction. + * + * @return the updated CronScheduleBuilder + * @see Trigger#MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY + */ + public CronScheduleBuilder withMisfireHandlingInstructionIgnoreMisfires() { + misfireInstruction = Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link CronTrigger#MISFIRE_INSTRUCTION_DO_NOTHING} instruction. + * + * @return the updated CronScheduleBuilder + * @see CronTrigger#MISFIRE_INSTRUCTION_DO_NOTHING + */ + public CronScheduleBuilder withMisfireHandlingInstructionDoNothing() { + misfireInstruction = CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link CronTrigger#MISFIRE_INSTRUCTION_FIRE_ONCE_NOW} instruction. + * + * @return the updated CronScheduleBuilder + * @see CronTrigger#MISFIRE_INSTRUCTION_FIRE_ONCE_NOW + */ + public CronScheduleBuilder withMisfireHandlingInstructionFireAndProceed() { + misfireInstruction = CronTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW; + return this; + } +} Index: 3rdParty_sources/quartz/org/quartz/CronTrigger.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/CronTrigger.java (.../CronTrigger.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/CronTrigger.java (.../CronTrigger.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,5 +1,5 @@ -/* - * Copyright 2004-2005 OpenSymphony +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -15,22 +15,15 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; -import java.text.ParseException; import java.util.Calendar; -import java.util.Date; import java.util.TimeZone; - /** - *- * A concrete
+ * The public interface for inspecting settings specific to a CronTrigger, . + * which is used to fire a{@link Trigger}
that is used to fire a{@link org.quartz.JobDetail}
- * at given moments in time, defined with Unix 'cron-like' definitions. - *{@link org.quartz.Job}
+ * at given moments in time, defined with Unix 'cron-like' schedule definitions. * ** For those unfamiliar with "cron", this means being able to create a firing @@ -139,7 +132,7 @@ *
* ** "0 15 10 ? * 6L 2002-2005"
- * Fire at 10:15am on every last friday of every month during the years 2002, 2003, 2004 and 2005
+ ** Fire at 10:15am on every last Friday of every month during the years 2002, 2003, 2004 and 2005
*@@ -168,23 +161,16 @@ * * * - * @see Trigger - * @see SimpleTrigger - * @see TriggerUtils + * @see CronScheduleBuilder + * @see TriggerBuilder * - * @author Sharada Jambula, James House + * @author jhouse * @author Contributions from Mads Henderson */ -public class CronTrigger extends Trigger { +public interface CronTrigger extends Trigger { - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Constants. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - + public static final long serialVersionUID = -8644953146451592766L; + /** * * Instructs the
*/ public static final int MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1; - + /** *{@link Scheduler}
that upon a mis-fire @@ -193,7 +179,7 @@ ** Instructs the
{@link Scheduler}
that upon a mis-fire @@ -205,765 +191,17 @@ */ public static final int MISFIRE_INSTRUCTION_DO_NOTHING = 2; - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Data members. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ + public String getCronExpression(); - private CronExpression cronEx = null; - private Date startTime = null; - private Date endTime = null; - private Date nextFireTime = null; - private Date previousFireTime = null; - private transient TimeZone timeZone = null; - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Constructors. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - /** *- * Create a
- * - *CronTrigger
with no settings. - *- * The start-time will also be set to the current time, and the time zone - * will be set the the system's default time zone. - *
- */ - public CronTrigger() { - super(); - setStartTime(new Date()); - setTimeZone(TimeZone.getDefault()); - } - - /** - *- * Create a
- * - *CronTrigger
with the given name and group. - *- * The start-time will also be set to the current time, and the time zone - * will be set the the system's default time zone. - *
- */ - public CronTrigger(String name, String group) { - super(name, group); - setStartTime(new Date()); - setTimeZone(TimeZone.getDefault()); - } - - /** - *- * Create a
- * - *CronTrigger
with the given name, group and - * expression. - *- * The start-time will also be set to the current time, and the time zone - * will be set the the system's default time zone. - *
- */ - public CronTrigger(String name, String group, String cronExpression) - throws ParseException { - super(name, group); - - setCronExpression(cronExpression); - - setStartTime(new Date()); - setTimeZone(TimeZone.getDefault()); - } - - /** - *- * Create a
- * - *CronTrigger
with the given name and group, and - * associated with the identified{@link org.quartz.JobDetail}
. - *- * The start-time will also be set to the current time, and the time zone - * will be set the the system's default time zone. - *
- */ - public CronTrigger(String name, String group, String jobName, - String jobGroup) { - super(name, group, jobName, jobGroup); - setStartTime(new Date()); - setTimeZone(TimeZone.getDefault()); - } - - /** - *- * Create a
- * - *CronTrigger
with the given name and group, - * associated with the identified{@link org.quartz.JobDetail}
, - * and with the given "cron" expression. - *- * The start-time will also be set to the current time, and the time zone - * will be set the the system's default time zone. - *
- */ - public CronTrigger(String name, String group, String jobName, - String jobGroup, String cronExpression) throws ParseException { - this(name, group, jobName, jobGroup, null, null, cronExpression, - TimeZone.getDefault()); - } - - /** - *- * Create a
- */ - public CronTrigger(String name, String group, String jobName, - String jobGroup, String cronExpression, TimeZone timeZone) - throws ParseException { - this(name, group, jobName, jobGroup, null, null, cronExpression, - timeZone); - } - - /** - *CronTrigger
with the given name and group, - * associated with the identified{@link org.quartz.JobDetail}
, - * and with the given "cron" expression resolved with respect to theTimeZone
. - *- * Create a
- * - *CronTrigger
that will occur at the given time, - * until the given end time. - *- * If null, the start-time will also be set to the current time, the time - * zone will be set the the system's default. - *
- * - * @param startTime - * ADate
set to the time for theTrigger
- * to fire. - * @param endTime - * ADate
set to the time for theTrigger
- * to quit repeat firing. - */ - public CronTrigger(String name, String group, String jobName, - String jobGroup, Date startTime, Date endTime, String cronExpression) - throws ParseException { - super(name, group, jobName, jobGroup); - - setCronExpression(cronExpression); - - if (startTime == null) startTime = new Date(); - setStartTime(startTime); - if (endTime != null) setEndTime(endTime); - setTimeZone(TimeZone.getDefault()); - - } - - /** - *- * Create a
- * - *CronTrigger
with fire time dictated by the - *cronExpression
resolved with respect to the specified - *timeZone
occuring from thestartTime
until - * the givenendTime
. - *- * If null, the start-time will also be set to the current time. If null, - * the time zone will be set to the system's default. - *
- * - * @param name - * of theTrigger
- * @param group - * of theTrigger
- * @param jobName, - * name of the{@link org.quartz.JobDetail}
- * executed on firetime - * @param jobGroup, - * group of the{@link org.quartz.JobDetail}
- * executed on firetime - * @param startTime - * ADate
set to the earliest time for theTrigger
- * to start firing. - * @param endTime - * ADate
set to the time for theTrigger
- * to quit repeat firing. - * @param cronExpression, - * A cron expression dictating the firing sequence of theTrigger
- * @param timeZone, - * Specifies for which time zone thecronExpression
- * should be interprted, i.e. the expression 0 0 10 * * ?, is - * resolved to 10:00 am in this time zone. - * @throws ParseException - * if thecronExpression
is invalid. - */ - public CronTrigger(String name, String group, String jobName, - String jobGroup, Date startTime, Date endTime, - String cronExpression, TimeZone timeZone) throws ParseException { - super(name, group, jobName, jobGroup); - - setCronExpression(cronExpression); - - if (startTime == null) startTime = new Date(); - setStartTime(startTime); - if (endTime != null) setEndTime(endTime); - if (timeZone == null) { - setTimeZone(TimeZone.getDefault()); - } else { - setTimeZone(timeZone); - } - } - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Interface. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - - public Object clone() { - CronTrigger copy = (CronTrigger) super.clone(); - copy.setCronExpression((CronExpression)cronEx.clone()); - return copy; - } - - public void setCronExpression(String cronExpression) throws ParseException { - this.cronEx = new CronExpression(cronExpression); - this.cronEx.setTimeZone(getTimeZone()); - } - - public String getCronExpression() { - return cronEx == null ? null : cronEx.getCronExpression(); - } - - public void setCronExpression(CronExpression cronExpression) { - this.cronEx = cronExpression; - this.timeZone = cronExpression.getTimeZone(); - } - - /** - *- * Get the time at which the
- */ - public Date getStartTime() { - return this.startTime; - } - - public void setStartTime(Date startTime) { - if (startTime == null) - throw new IllegalArgumentException("Start time cannot be null"); - - Date eTime = getEndTime(); - if (eTime != null && startTime != null && eTime.before(startTime)) - throw new IllegalArgumentException( - "End time cannot be before start time"); - - // round off millisecond... - // Note timeZone is not needed here as parameter for - // Calendar.getInstance(), - // since time zone is implicit when using a Date in the setTime method. - Calendar cl = Calendar.getInstance(); - cl.setTime(startTime); - cl.set(Calendar.MILLISECOND, 0); - - this.startTime = cl.getTime(); - } - - /** - *CronTrigger
should occur. - *- * Get the time at which the
- * - * @see #getFinalFireTime() - */ - public Date getEndTime() { - return this.endTime; - } - - public void setEndTime(Date endTime) { - Date sTime = getStartTime(); - if (sTime != null && endTime != null && sTime.after(endTime)) - throw new IllegalArgumentException( - "End time cannot be before start time"); - - this.endTime = endTime; - } - - /** - *CronTrigger
should quit - * repeating - even if repeastCount isn't yet satisfied. - *- * Returns the next time at which the
- */ - public Date getNextFireTime() { - return this.nextFireTime; - } - - /** - *CronTrigger
will fire. - * If the trigger will not fire again,null
will be - * returned. The value returned is not guaranteed to be valid until after - * theTrigger
has been added to the scheduler. - *- * Returns the previous time at which the
CronTrigger
will - * fire. If the trigger has not yet fired,null
will be - * returned. - */ - public Date getPreviousFireTime() { - return this.previousFireTime; - } - - /** - *- * Sets the next time at which the
- */ - public void setNextFireTime(Date nextFireTime) { - this.nextFireTime = nextFireTime; - } - - /** - *CronTrigger
will fire. - * This method should not be invoked by client code. - *- * Set the previous time at which the
- * - *SimpleTrigger
fired. - *- * This method should not be invoked by client code. - *
- */ - public void setPreviousFireTime(Date previousFireTime) { - this.previousFireTime = previousFireTime; - } - - /** - ** Returns the time zone for which the
*/ - public TimeZone getTimeZone() { - - if(cronEx != null) return cronEx.getTimeZone(); - - if (timeZone == null) timeZone = TimeZone.getDefault(); - return timeZone; - } + public TimeZone getTimeZone(); - /** - *cronExpression
of * thisCronTrigger
will be resolved. *- * Sets the time zone for which the
- */ - public void setTimeZone(TimeZone timeZone) { - if(cronEx != null) cronEx.setTimeZone(timeZone); - this.timeZone = timeZone; - } + public String getExpressionSummary(); - /** - *cronExpression
of this - *CronTrigger
will be resolved. - *- * Returns the next time at which the
- * - *CronTrigger
will fire, - * after the given time. If the trigger will not fire after the given time, - *null
will be returned. - *- * Note that the date returned is NOT validated against the related - * org.quartz.Calendar (if any) - *
- */ - public Date getFireTimeAfter(Date afterTime) { - if (afterTime == null) afterTime = new Date(); - - if (startTime.after(afterTime)) - afterTime = new Date(startTime.getTime() - 1000l); - - Date pot = getTimeAfter(afterTime); - if (endTime != null && pot != null && pot.after(endTime)) return null; - - return pot; - } - - /** - *- * Returns the final time at which the
- * - *CronTrigger
will - * fire. - *- * Note that the return time *may* be in the past. and the date returned is - * not validated against org.quartz.calendar - *
- */ - public Date getFinalFireTime() { - if (this.endTime != null) return getTimeBefore(this.endTime); - else - return null; - } - - /** - *- * Determines whether or not the
- */ - public boolean mayFireAgain() { - return (getNextFireTime() != null); - } - - protected boolean validateMisfireInstruction(int misfireInstruction) { - if (misfireInstruction < MISFIRE_INSTRUCTION_SMART_POLICY) - return false; - - if (misfireInstruction > MISFIRE_INSTRUCTION_DO_NOTHING) return false; - - return true; - } - - /** - *CronTrigger
will occur - * again. - *- * Updates the
- * - *CronTrigger
's state based on the - * MISFIRE_INSTRUCTION_XXX that was selected when theSimpleTrigger
- * was created. - *- * If the misfire instruction is set to MISFIRE_INSTRUCTION_SMART_POLICY, - * then the following scheme will be used:
- *- *
- * - */ - public void updateAfterMisfire(org.quartz.Calendar cal) { - int instr = getMisfireInstruction(); - - if (instr == MISFIRE_INSTRUCTION_SMART_POLICY) - instr = MISFIRE_INSTRUCTION_FIRE_ONCE_NOW; - - if (instr == MISFIRE_INSTRUCTION_DO_NOTHING) { - Date newFireTime = getFireTimeAfter(new Date()); - while (newFireTime != null && cal != null - && !cal.isTimeIncluded(newFireTime.getTime())) { - newFireTime = getFireTimeAfter(newFireTime); - } - setNextFireTime(newFireTime); - } else if (instr == MISFIRE_INSTRUCTION_FIRE_ONCE_NOW) { - setNextFireTime(new Date()); - } - } - - /** - *- The instruction will be interpreted as
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW
- *- * Determines whether the date and (optionally) time of the given Calendar - * instance falls on a scheduled fire-time of this trigger. - *
- * - *- * Equivalent to calling
- * - * @param test the date to compare - * - * @see #willFireOn(Calendar, boolean) - */ - public boolean willFireOn(Calendar test) { - return willFireOn(test, false); - } - - /** - *willFireOn(cal, false)
. - *- * Determines whether the date and (optionally) time of the given Calendar - * instance falls on a scheduled fire-time of this trigger. - *
- * - *- * Note that the value returned is NOT validated against the related - * org.quartz.Calendar (if any) - *
- * - * @param test the date to compare - * @param dayOnly if set to true, the method will only determine if the - * trigger will fire during the day represented by the given Calendar - * (hours, minutes and seconds will be ignored). - * @see #willFireOn(Calendar) - */ - public boolean willFireOn(Calendar test, boolean dayOnly) { - - test = (Calendar) test.clone(); - - test.set(Calendar.MILLISECOND, 0); // don't compare millis. - - if(dayOnly) { - test.set(Calendar.HOUR, 0); - test.set(Calendar.MINUTE, 0); - test.set(Calendar.SECOND, 0); - } - - Date testTime = test.getTime(); - - Date fta = getFireTimeAfter(new Date(test.getTime().getTime() - 1000)); - - Calendar p = Calendar.getInstance(test.getTimeZone()); - p.setTime(fta); - - int year = p.get(Calendar.YEAR); - int month = p.get(Calendar.MONTH); - int day = p.get(Calendar.DATE); - - if(dayOnly) { - return (year == test.get(Calendar.YEAR) - && month == test.get(Calendar.MONTH) - && day == test.get(Calendar.DATE)); - } - - while(fta.before(testTime)) { - fta = getFireTimeAfter(fta); - } - - if(fta.equals(testTime)) - return true; - - return false; - } - - /** - *- * Called after the
- * - * @param context - * is the{@link Scheduler}
has executed the - *{@link org.quartz.JobDetail}
associated with theTrigger
- * in order to get the final instruction code from the trigger. - *JobExecutionContext
that was used by the - *Job
'sexecute(xx)
method. - * @param result - * is theJobExecutionException
thrown by the - *Job
, if any (may be null). - * @return one of the Trigger.INSTRUCTION_XXX constants. - * - * @see #INSTRUCTION_NOOP - * @see #INSTRUCTION_RE_EXECUTE_JOB - * @see #INSTRUCTION_DELETE_TRIGGER - * @see #INSTRUCTION_SET_TRIGGER_COMPLETE - * @see #triggered(Calendar) - */ - public int executionComplete(JobExecutionContext context, - JobExecutionException result) { - if (result != null && result.refireImmediately()) - return INSTRUCTION_RE_EXECUTE_JOB; - - if (result != null && result.unscheduleFiringTrigger()) - return INSTRUCTION_SET_TRIGGER_COMPLETE; - - if (result != null && result.unscheduleAllTriggers()) - return INSTRUCTION_SET_ALL_JOB_TRIGGERS_COMPLETE; - - if (!mayFireAgain()) return INSTRUCTION_DELETE_TRIGGER; - - return INSTRUCTION_NOOP; - } - - /** - *- * Called when the
- * - * @see #executionComplete(JobExecutionContext, JobExecutionException) - */ - public void triggered(org.quartz.Calendar calendar) { - previousFireTime = nextFireTime; - nextFireTime = getFireTimeAfter(nextFireTime); - - while (nextFireTime != null && calendar != null - && !calendar.isTimeIncluded(nextFireTime.getTime())) { - nextFireTime = getFireTimeAfter(nextFireTime); - } - } - - /** - * - * @see org.quartz.Trigger#updateWithNewCalendar(org.quartz.Calendar, long) - */ - public void updateWithNewCalendar(org.quartz.Calendar calendar, long misfireThreshold) - { - nextFireTime = getFireTimeAfter(previousFireTime); - - Date now = new Date(); - do { - while (nextFireTime != null && calendar != null - && !calendar.isTimeIncluded(nextFireTime.getTime())) { - nextFireTime = getFireTimeAfter(nextFireTime); - } - - if(nextFireTime != null && nextFireTime.before(now)) { - long diff = now.getTime() - nextFireTime.getTime(); - if(diff >= misfireThreshold) { - nextFireTime = getFireTimeAfter(nextFireTime); - continue; - } - } - }while(false); - } - - /** - *{@link Scheduler}
has decided to 'fire' - * the trigger (execute the associatedJob
), in order to - * give theTrigger
a chance to update itself for its next - * triggering (if any). - *- * Called by the scheduler at the time a
- * - *Trigger
is first - * added to the scheduler, in order to have theTrigger
- * compute its first fire time, based on any associated calendar. - *- * After this method has been called,
- * - * @return the first time at which thegetNextFireTime()
- * should return a valid answer. - *Trigger
will be fired - * by the scheduler, which is also the same valuegetNextFireTime()
- * will return (until after the first firing of theTrigger
). - * - */ - public Date computeFirstFireTime(org.quartz.Calendar calendar) { - nextFireTime = getFireTimeAfter(new Date(startTime.getTime() - 1000l)); - - while (nextFireTime != null && calendar != null - && !calendar.isTimeIncluded(nextFireTime.getTime())) { - nextFireTime = getFireTimeAfter(nextFireTime); - } - - return nextFireTime; - } - - public String getExpressionSummary() { - return cronEx == null ? null : cronEx.getExpressionSummary(); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Computation Functions - // - //////////////////////////////////////////////////////////////////////////// - - protected Date getTimeAfter(Date afterTime) { - return cronEx.getTimeAfter(afterTime); - } - - protected Date getTimeBefore(Date endTime) - { - return null; - } - - public static void main(String[] args) // TODO: remove method after good - // unit testing - throws Exception { - - String expr = "15 10 0/4 * * ?"; - if(args != null && args.length > 0 && args[0] != null) - expr = args[0]; - - CronTrigger ct = new CronTrigger("t", "g", "j", "g", new Date(), null, expr); - ct.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); - System.err.println(ct.getExpressionSummary()); - System.err.println("tz=" + ct.getTimeZone().getID()); - System.err.println(); - - java.util.List times = TriggerUtils.computeFireTimes(ct, null, 25); - - for (int i = 0; i < times.size(); i++) { - System.err.println("firetime = " + times.get(i)); - } - - Calendar tt = Calendar.getInstance(); - tt.set(Calendar.DATE, 17); - tt.set(Calendar.MONTH, 5 - 1); - tt.set(Calendar.HOUR, 11); - tt.set(Calendar.MINUTE, 0); - tt.set(Calendar.SECOND, 7); - - System.err.println("\nWill fire on: " + tt.getTime() + " -- " + ct.willFireOn(tt, false)); - - -// CRON Expression: 0 0 9 * * ? -// -// TimeZone.getDefault().getDisplayName() = Central African Time -// TimeZone.getDefault().getID() = Africa/Harare - // -//// System.err.println(); -//// System.err.println(); -//// System.err.println(); -//// System.err.println("Daylight test:"); -//// -//// CronTrigger trigger = new CronTrigger(); -//// -//// TimeZone timeZone = TimeZone.getTimeZone("America/Los_Angeles"); -//// // TimeZone timeZone = TimeZone.getDefault(); -//// -//// trigger.setTimeZone(timeZone); -//// trigger.setCronExpression("0 0 1 ? 4 *"); -//// -//// Date start = new Date(1056319200000L); -//// Date end = new Date(1087682399000L); -//// -//// trigger.setStartTime(start); -//// trigger.setEndTime(end); -//// -//// Date next = new Date(1056232800000L); -//// while (next != null) { -//// next = trigger.getFireTimeAfter(next); -//// if (next != null) { -//// Calendar cal = Calendar.getInstance(); -//// cal.setTimeZone(timeZone); -//// cal.setTime(next); -//// System.err.println(cal.get(Calendar.MONTH) + "/" -//// + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR) -//// + " - " + cal.get(Calendar.HOUR_OF_DAY) + ":" -//// + cal.get(Calendar.MINUTE)); -//// } -//// } -//// -//// System.err.println(); -//// System.err.println(); -//// System.err.println(); -//// System.err.println("Midnight test:"); -//// -//// trigger = new CronTrigger(); -//// -//// timeZone = TimeZone.getTimeZone("Asia/Jerusalem"); -//// // timeZone = TimeZone.getTimeZone("America/Los_Angeles"); -//// // TimeZone timeZone = TimeZone.getDefault(); -//// -//// trigger.setTimeZone(timeZone); -//// trigger.setCronExpression("0 /15 * ? 4 *"); -//// -//// start = new Date(1056319200000L); -//// end = new Date(1087682399000L); -//// -//// trigger.setStartTime(start); -//// trigger.setEndTime(end); -//// -//// next = new Date(1056232800000L); -//// while (next != null) { -//// next = trigger.getFireTimeAfter(next); -//// if (next != null) { -//// Calendar cal = Calendar.getInstance(); -//// cal.setTimeZone(timeZone); -//// cal.setTime(next); -//// System.err.println(cal.get(Calendar.MONTH) + "/" -//// + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR) -//// + " - " + cal.get(Calendar.HOUR_OF_DAY) + ":" -//// + cal.get(Calendar.MINUTE)); -//// } -//// } - - } + TriggerBuildergetTriggerBuilder(); } - Index: 3rdParty_sources/quartz/org/quartz/DailyTimeIntervalScheduleBuilder.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/DailyTimeIntervalScheduleBuilder.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/DailyTimeIntervalScheduleBuilder.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,413 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +package org.quartz; + +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import org.quartz.DateBuilder.IntervalUnit; +import org.quartz.impl.triggers.DailyTimeIntervalTriggerImpl; +import org.quartz.spi.MutableTrigger; + +/** + * A {@link ScheduleBuilder} implementation that build schedule for DailyTimeIntervalTrigger. + * + * This builder provide an extra convenient method for you to set the trigger's endTimeOfDay. You may + * use either endingDailyAt() or endingDailyAfterCount() to set the value. The later will auto calculate + * your endTimeOfDay by using the interval, intervalUnit and startTimeOfDay to perform the calculation. + * + *
When using endingDailyAfterCount(), you should note that it is used to calculating endTimeOfDay. So + * if your startTime on the first day is already pass by a time that would not add up to the count you + * expected, until the next day comes. Remember that DailyTimeIntervalTrigger will use startTimeOfDay + * and endTimeOfDay as fresh per each day! + * + *
Quartz provides a builder-style API for constructing scheduling-related + * entities via a Domain-Specific Language (DSL). The DSL can best be + * utilized through the usage of static imports of the methods on the classes + *
+ * + *TriggerBuilder
,JobBuilder
, + *DateBuilder
,JobKey
,TriggerKey
+ * and the variousScheduleBuilder
implementations.Client code can then use the DSL to write code such as this:
+ *+ * JobDetail job = newJob(MyJob.class) + * .withIdentity("myJob") + * .build(); + * + * Trigger trigger = newTrigger() + * .withIdentity(triggerKey("myTrigger", "myTriggerGroup")) + * .withSchedule(onDaysOfTheWeek(MONDAY, THURSDAY)) + * .startAt(futureDate(10, MINUTES)) + * .build(); + * + * scheduler.scheduleJob(job, trigger); + *+ * + * @since 2.1.0 + * + * @author James House + * @author Zemian Deng+ */ +public class DailyTimeIntervalScheduleBuilder extends ScheduleBuilder { + + private int interval = 1; + private IntervalUnit intervalUnit = IntervalUnit.MINUTE; + private Set daysOfWeek; + private TimeOfDay startTimeOfDay; + private TimeOfDay endTimeOfDay; + private int repeatCount = DailyTimeIntervalTrigger.REPEAT_INDEFINITELY; + + private int misfireInstruction = CalendarIntervalTrigger.MISFIRE_INSTRUCTION_SMART_POLICY; + + /** + * A set of all days of the week. + * + * The set contains all values between {@link java.util.Calendar#SUNDAY} and {@link java.util.Calendar#SATURDAY} + * (the integers from 1 through 7). + */ + public static final Set ALL_DAYS_OF_THE_WEEK; + + /** + * A set of the business days of the week (for locales similar to the USA). + * + * The set contains all values between {@link java.util.Calendar#MONDAY} and {@link java.util.Calendar#FRIDAY} + * (the integers from 2 through 6). + */ + public static final Set MONDAY_THROUGH_FRIDAY; + + /** + * A set of the weekend days of the week (for locales similar to the USA). + * + * The set contains {@link java.util.Calendar#SATURDAY} and {@link java.util.Calendar#SUNDAY} + */ + public static final Set SATURDAY_AND_SUNDAY; + + static { + Set t = new HashSet (7); + for(int i=Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) + t.add(i); + ALL_DAYS_OF_THE_WEEK = Collections.unmodifiableSet(t); + + t = new HashSet (5); + for(int i=Calendar.MONDAY; i <= Calendar.FRIDAY; i++) + t.add(i); + MONDAY_THROUGH_FRIDAY = Collections.unmodifiableSet(t); + + t = new HashSet (2); + t.add(Calendar.SUNDAY); + t.add(Calendar.SATURDAY); + SATURDAY_AND_SUNDAY = Collections.unmodifiableSet(t); + } + + protected DailyTimeIntervalScheduleBuilder() { + } + + /** + * Create a DailyTimeIntervalScheduleBuilder. + * + * @return the new DailyTimeIntervalScheduleBuilder + */ + public static DailyTimeIntervalScheduleBuilder dailyTimeIntervalSchedule() { + return new DailyTimeIntervalScheduleBuilder(); + } + + /** + * Build the actual Trigger -- NOT intended to be invoked by end users, + * but will rather be invoked by a TriggerBuilder which this + * ScheduleBuilder is given to. + * + * @see TriggerBuilder#withSchedule(ScheduleBuilder) + */ + @Override + public MutableTrigger build() { + + DailyTimeIntervalTriggerImpl st = new DailyTimeIntervalTriggerImpl(); + st.setRepeatInterval(interval); + st.setRepeatIntervalUnit(intervalUnit); + st.setMisfireInstruction(misfireInstruction); + st.setRepeatCount(repeatCount); + + if(daysOfWeek != null) + st.setDaysOfWeek(daysOfWeek); + else + st.setDaysOfWeek(ALL_DAYS_OF_THE_WEEK); + + if(startTimeOfDay != null) + st.setStartTimeOfDay(startTimeOfDay); + else + st.setStartTimeOfDay(TimeOfDay.hourAndMinuteOfDay(0, 0)); + + if(endTimeOfDay != null) + st.setEndTimeOfDay(endTimeOfDay); + else + st.setEndTimeOfDay(TimeOfDay.hourMinuteAndSecondOfDay(23, 59, 59)); + + return st; + } + + /** + * Specify the time unit and interval for the Trigger to be produced. + * + * @param timeInterval the interval at which the trigger should repeat. + * @param unit the time unit (IntervalUnit) of the interval. The only intervals that are valid for this type of + * trigger are {@link IntervalUnit#SECOND}, {@link IntervalUnit#MINUTE}, and {@link IntervalUnit#HOUR}. + * @return the updated DailyTimeIntervalScheduleBuilder + * @see DailyTimeIntervalTrigger#getRepeatInterval() + * @see DailyTimeIntervalTrigger#getRepeatIntervalUnit() + */ + public DailyTimeIntervalScheduleBuilder withInterval(int timeInterval, IntervalUnit unit) { + if (unit == null || !(unit.equals(IntervalUnit.SECOND) || + unit.equals(IntervalUnit.MINUTE) ||unit.equals(IntervalUnit.HOUR))) + throw new IllegalArgumentException("Invalid repeat IntervalUnit (must be SECOND, MINUTE or HOUR)."); + validateInterval(timeInterval); + this.interval = timeInterval; + this.intervalUnit = unit; + return this; + } + + /** + * Specify an interval in the IntervalUnit.SECOND that the produced + * Trigger will repeat at. + * + * @param intervalInSeconds the number of seconds at which the trigger should repeat. + * @return the updated DailyTimeIntervalScheduleBuilder + * @see DailyTimeIntervalTrigger#getRepeatInterval() + * @see DailyTimeIntervalTrigger#getRepeatIntervalUnit() + */ + public DailyTimeIntervalScheduleBuilder withIntervalInSeconds(int intervalInSeconds) { + withInterval(intervalInSeconds, IntervalUnit.SECOND); + return this; + } + + /** + * Specify an interval in the IntervalUnit.MINUTE that the produced + * Trigger will repeat at. + * + * @param intervalInMinutes the number of minutes at which the trigger should repeat. + * @return the updated CalendarIntervalScheduleBuilder + * @see DailyTimeIntervalTrigger#getRepeatInterval() + * @see DailyTimeIntervalTrigger#getRepeatIntervalUnit() + */ + public DailyTimeIntervalScheduleBuilder withIntervalInMinutes(int intervalInMinutes) { + withInterval(intervalInMinutes, IntervalUnit.MINUTE); + return this; + } + + /** + * Specify an interval in the IntervalUnit.HOUR that the produced + * Trigger will repeat at. + * + * @param intervalInHours the number of hours at which the trigger should repeat. + * @return the updated DailyTimeIntervalScheduleBuilder + * @see DailyTimeIntervalTrigger#getRepeatInterval() + * @see DailyTimeIntervalTrigger#getRepeatIntervalUnit() + */ + public DailyTimeIntervalScheduleBuilder withIntervalInHours(int intervalInHours) { + withInterval(intervalInHours, IntervalUnit.HOUR); + return this; + } + + /** + * Set the trigger to fire on the given days of the week. + * + * @param onDaysOfWeek a Set containing the integers representing the days of the week, per the values 1-7 as defined by + * {@link java.util.Calendar#SUNDAY} - {@link java.util.Calendar#SATURDAY}. + * @return the updated DailyTimeIntervalScheduleBuilder + */ + public DailyTimeIntervalScheduleBuilder onDaysOfTheWeek(Set onDaysOfWeek) { + if(onDaysOfWeek == null || onDaysOfWeek.size() == 0) + throw new IllegalArgumentException("Days of week must be an non-empty set."); + for (Integer day : onDaysOfWeek) + if (!ALL_DAYS_OF_THE_WEEK.contains(day)) + throw new IllegalArgumentException("Invalid value for day of week: " + day); + + this.daysOfWeek = onDaysOfWeek; + return this; + } + + /** + * Set the trigger to fire on the given days of the week. + * + * @param onDaysOfWeek a variable length list of Integers representing the days of the week, per the values 1-7 as + * defined by {@link java.util.Calendar#SUNDAY} - {@link java.util.Calendar#SATURDAY}. + * @return the updated DailyTimeIntervalScheduleBuilder + */ + public DailyTimeIntervalScheduleBuilder onDaysOfTheWeek(Integer ... onDaysOfWeek) { + Set daysAsSet = new HashSet (12); + Collections.addAll(daysAsSet, onDaysOfWeek); + return onDaysOfTheWeek(daysAsSet); + } + + /** + * Set the trigger to fire on the days from Monday through Friday. + * + * @return the updated DailyTimeIntervalScheduleBuilder + */ + public DailyTimeIntervalScheduleBuilder onMondayThroughFriday() { + this.daysOfWeek = MONDAY_THROUGH_FRIDAY; + return this; + } + + /** + * Set the trigger to fire on the days Saturday and Sunday. + * + * @return the updated DailyTimeIntervalScheduleBuilder + */ + public DailyTimeIntervalScheduleBuilder onSaturdayAndSunday() { + this.daysOfWeek = SATURDAY_AND_SUNDAY; + return this; + } + + /** + * Set the trigger to fire on all days of the week. + * + * @return the updated DailyTimeIntervalScheduleBuilder + */ + public DailyTimeIntervalScheduleBuilder onEveryDay() { + this.daysOfWeek = ALL_DAYS_OF_THE_WEEK; + return this; + } + + /** + * Set the trigger to begin firing each day at the given time. + * + * @return the updated DailyTimeIntervalScheduleBuilder + */ + public DailyTimeIntervalScheduleBuilder startingDailyAt(TimeOfDay timeOfDay) { + if(timeOfDay == null) + throw new IllegalArgumentException("Start time of day cannot be null!"); + + this.startTimeOfDay = timeOfDay; + return this; + } + + /** + * Set the startTimeOfDay for this trigger to end firing each day at the given time. + * + * @return the updated DailyTimeIntervalScheduleBuilder + */ + public DailyTimeIntervalScheduleBuilder endingDailyAt(TimeOfDay timeOfDay) { + this.endTimeOfDay = timeOfDay; + return this; + } + + /** + * Calculate and set the endTimeOfDay using count, interval and starTimeOfDay. This means + * that these must be set before this method is call. + * + * @return the updated DailyTimeIntervalScheduleBuilder + */ + public DailyTimeIntervalScheduleBuilder endingDailyAfterCount(int count) { + if(count <=0) + throw new IllegalArgumentException("Ending daily after count must be a positive number!"); + + if(startTimeOfDay == null) + throw new IllegalArgumentException("You must set the startDailyAt() before calling this endingDailyAfterCount()!"); + + Date today = new Date(); + Date startTimeOfDayDate = startTimeOfDay.getTimeOfDayForDate(today); + Date maxEndTimeOfDayDate = TimeOfDay.hourMinuteAndSecondOfDay(23, 59, 59).getTimeOfDayForDate(today); + long remainingMillisInDay = maxEndTimeOfDayDate.getTime() - startTimeOfDayDate.getTime(); + long intervalInMillis; + if (intervalUnit == IntervalUnit.SECOND) + intervalInMillis = interval * 1000L; + else if (intervalUnit == IntervalUnit.MINUTE) + intervalInMillis = interval * 1000L * 60; + else if (intervalUnit == IntervalUnit.HOUR) + intervalInMillis = interval * 1000L * 60 * 24; + else + throw new IllegalArgumentException("The IntervalUnit: " + intervalUnit + " is invalid for this trigger."); + + if (remainingMillisInDay - intervalInMillis <= 0) + throw new IllegalArgumentException("The startTimeOfDay is too late with given Interval and IntervalUnit values."); + + long maxNumOfCount = (remainingMillisInDay / intervalInMillis); + if (count > maxNumOfCount) + throw new IllegalArgumentException("The given count " + count + " is too large! The max you can set is " + maxNumOfCount); + + long incrementInMillis = (count - 1) * intervalInMillis; + Date endTimeOfDayDate = new Date(startTimeOfDayDate.getTime() + incrementInMillis); + + if (endTimeOfDayDate.getTime() > maxEndTimeOfDayDate.getTime()) + throw new IllegalArgumentException("The given count " + count + " is too large! The max you can set is " + maxNumOfCount); + + Calendar cal = Calendar.getInstance(); + cal.setTime(endTimeOfDayDate); + int hour = cal.get(Calendar.HOUR_OF_DAY); + int minute = cal.get(Calendar.MINUTE); + int second = cal.get(Calendar.SECOND); + + endTimeOfDay = TimeOfDay.hourMinuteAndSecondOfDay(hour, minute, second); + return this; + } + + /** + * If the Trigger misfires, use the + * {@link Trigger#MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY} instruction. + * + * @return the updated DailyTimeIntervalScheduleBuilder + * @see Trigger#MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY + */ + public DailyTimeIntervalScheduleBuilder withMisfireHandlingInstructionIgnoreMisfires() { + misfireInstruction = Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link DailyTimeIntervalTrigger#MISFIRE_INSTRUCTION_DO_NOTHING} instruction. + * + * @return the updated DailyTimeIntervalScheduleBuilder + * @see DailyTimeIntervalTrigger#MISFIRE_INSTRUCTION_DO_NOTHING + */ + public DailyTimeIntervalScheduleBuilder withMisfireHandlingInstructionDoNothing() { + misfireInstruction = DailyTimeIntervalTrigger.MISFIRE_INSTRUCTION_DO_NOTHING; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link DailyTimeIntervalTrigger#MISFIRE_INSTRUCTION_FIRE_ONCE_NOW} instruction. + * + * @return the updated DailyTimeIntervalScheduleBuilder + * @see DailyTimeIntervalTrigger#MISFIRE_INSTRUCTION_FIRE_ONCE_NOW + */ + public DailyTimeIntervalScheduleBuilder withMisfireHandlingInstructionFireAndProceed() { + misfireInstruction = CalendarIntervalTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW; + return this; + } + + /** + * Set number of times for interval to repeat. + * + * Note: if you want total count = 1 (at start time) + repeatCount
+ * + * @return the new DailyTimeIntervalScheduleBuilder + */ + public DailyTimeIntervalScheduleBuilder withRepeatCount(int repeatCount) { + this.repeatCount = repeatCount; + return this; + } + + private void validateInterval(int timeInterval) { + if(timeInterval <= 0) + throw new IllegalArgumentException("Interval must be a positive value."); + } +} Index: 3rdParty_sources/quartz/org/quartz/DailyTimeIntervalTrigger.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/DailyTimeIntervalTrigger.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/DailyTimeIntervalTrigger.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,138 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +package org.quartz; + +import java.util.Calendar; +import java.util.Set; + +import org.quartz.DateBuilder.IntervalUnit; + +/** + * A{@link Trigger}
that is used to fire a{@link org.quartz.JobDetail}
+ * based upon daily repeating time intervals. + * + *The trigger will fire every N (see {@link #getRepeatInterval()} ) seconds, minutes or hours + * (see {@link #getRepeatIntervalUnit()}) during a given time window on specified days of the week.
+ * + *For example#1, a trigger can be set to fire every 72 minutes between 8:00 and 11:00 everyday. It's fire times would + * be 8:00, 9:12, 10:24, then next day would repeat: 8:00, 9:12, 10:24 again.
+ * + *For example#2, a trigger can be set to fire every 23 minutes between 9:20 and 16:47 Monday through Friday.
+ * + *On each day, the starting fire time is reset to startTimeOfDay value, and then it will add repeatInterval value to it until + * the endTimeOfDay is reached. If you set daysOfWeek values, then fire time will only occur during those week days period.
+ * + *The default values for fields if not set are: startTimeOfDay defaults to 00:00:00, the endTimeOfDay default to 23:59:59, + * and daysOfWeek is default to every day. The startTime default to current time-stamp now, while endTime has not value.
+ * + *If startTime is before startTimeOfDay, then it has no affect. Else if startTime after startTimeOfDay, then the first fire time + * for that day will be normal startTimeOfDay incremental values after startTime value. Same reversal logic is applied to endTime + * with endTimeOfDay.
+ * + * @see DailyTimeIntervalScheduleBuilder + * + * @since 2.1.0 + * + * @author James House + * @author Zemian Deng+ */ +public interface DailyTimeIntervalTrigger extends Trigger { + + /** + * + * Used to indicate the 'repeat count' of the trigger is indefinite. Or in + * other words, the trigger should repeat continually until the trigger's + * ending timestamp. + *
+ */ + public static final int REPEAT_INDEFINITELY = -1; + + /** + *+ * Instructs the
+ */ + public static final int MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1; + + /** + *{@link Scheduler}
that upon a mis-fire + * situation, the{@link DailyTimeIntervalTrigger}
wants to be + * fired now byScheduler
. + *+ * Instructs the
+ */ + public static final int MISFIRE_INSTRUCTION_DO_NOTHING = 2; + + /** + *{@link Scheduler}
that upon a mis-fire + * situation, the{@link DailyTimeIntervalTrigger}
wants to have it's + * next-fire-time updated to the next time in the schedule after the + * current time (taking into account any associated{@link Calendar}
, + * but it does not want to be fired now. + *Get the interval unit - the time unit on with the interval applies.
+ * + *The only intervals that are valid for this type of trigger are {@link IntervalUnit#SECOND}, + * {@link IntervalUnit#MINUTE}, and {@link IntervalUnit#HOUR}.
+ */ + public IntervalUnit getRepeatIntervalUnit(); + + /** + *+ * Get the the number of times for interval this trigger should + * repeat, after which it will be automatically deleted. + *
+ * + * @see #REPEAT_INDEFINITELY + */ + public int getRepeatCount(); + + /** + *+ * Get the the time interval that will be added to the
+ */ + public int getRepeatInterval(); + + /** + * The time of day to start firing at the given interval. + */ + public TimeOfDay getStartTimeOfDay(); + + /** + * The time of day to complete firing at the given interval. + */ + public TimeOfDay getEndTimeOfDay(); + + /** + * The days of the week upon which to fire. + * + * @return a Set containing the integers representing the days of the week, per the values 1-7 as defined by + * {@link java.util.Calendar#SUNDAY} - {@link java.util.Calendar#SATURDAY}. + */ + public SetDateIntervalTrigger
's + * fire time (in the set repeat interval unit) in order to calculate the time of the + * next trigger repeat. + *getDaysOfWeek(); + + /** + * + * Get the number of times the
+ */ + public int getTimesTriggered(); + + public TriggerBuilderDateIntervalTrigger
has already + * fired. + *getTriggerBuilder(); +} Index: 3rdParty_sources/quartz/org/quartz/DateBuilder.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/DateBuilder.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/DateBuilder.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,1021 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +/** + * DateBuilder
is used to conveniently create + *java.util.Date
instances that meet particular criteria. + * + *Quartz provides a builder-style API for constructing scheduling-related + * entities via a Domain-Specific Language (DSL). The DSL can best be + * utilized through the usage of static imports of the methods on the classes + *
+ * + *TriggerBuilder
,JobBuilder
, + *DateBuilder
,JobKey
,TriggerKey
+ * and the variousScheduleBuilder
implementations.Client code can then use the DSL to write code such as this:
+ *+ * JobDetail job = newJob(MyJob.class) + * .withIdentity("myJob") + * .build(); + * + * Trigger trigger = newTrigger() + * .withIdentity(triggerKey("myTrigger", "myTriggerGroup")) + * .withSchedule(simpleSchedule() + * .withIntervalInHours(1) + * .repeatForever()) + * .startAt(futureDate(10, MINUTES)) + * .build(); + * + * scheduler.scheduleJob(job, trigger); + *+ * + * @see TriggerBuilder + * @see JobBuilder + */ +public class DateBuilder { + + public enum IntervalUnit { MILLISECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR } + + public static final int SUNDAY = 1; + + public static final int MONDAY = 2; + + public static final int TUESDAY = 3; + + public static final int WEDNESDAY = 4; + + public static final int THURSDAY = 5; + + public static final int FRIDAY = 6; + + public static final int SATURDAY = 7; + + public static final int JANUARY = 1; + + public static final int FEBRUARY = 2; + + public static final int MARCH = 3; + + public static final int APRIL = 4; + + public static final int MAY = 5; + + public static final int JUNE = 6; + + public static final int JULY = 7; + + public static final int AUGUST = 8; + + public static final int SEPTEMBER = 9; + + public static final int OCTOBER = 10; + + public static final int NOVEMBER = 11; + + public static final int DECEMBER = 12; + + public static final long MILLISECONDS_IN_MINUTE = 60l * 1000l; + + public static final long MILLISECONDS_IN_HOUR = 60l * 60l * 1000l; + + public static final long SECONDS_IN_MOST_DAYS = 24l * 60l * 60L; + + public static final long MILLISECONDS_IN_DAY = SECONDS_IN_MOST_DAYS * 1000l; + + private int month; + private int day; + private int year; + private int hour; + private int minute; + private int second; + private TimeZone tz; + private Locale lc; + + /** + * Create a DateBuilder, with initial settings for the current date and time in the system default timezone. + */ + private DateBuilder() { + Calendar cal = Calendar.getInstance(); + + month = cal.get(Calendar.MONTH) + 1; + day = cal.get(Calendar.DAY_OF_MONTH); + year = cal.get(Calendar.YEAR); + hour = cal.get(Calendar.HOUR_OF_DAY); + minute = cal.get(Calendar.MINUTE); + second = cal.get(Calendar.SECOND); + } + + /** + * Create a DateBuilder, with initial settings for the current date and time in the given timezone. + */ + private DateBuilder(TimeZone tz) { + Calendar cal = Calendar.getInstance(tz); + + this.tz = tz; + month = cal.get(Calendar.MONTH) + 1; + day = cal.get(Calendar.DAY_OF_MONTH); + year = cal.get(Calendar.YEAR); + hour = cal.get(Calendar.HOUR_OF_DAY); + minute = cal.get(Calendar.MINUTE); + second = cal.get(Calendar.SECOND); + } + + /** + * Create a DateBuilder, with initial settings for the current date and time in the given locale. + */ + private DateBuilder(Locale lc) { + Calendar cal = Calendar.getInstance(lc); + + this.lc = lc; + month = cal.get(Calendar.MONTH) + 1; + day = cal.get(Calendar.DAY_OF_MONTH); + year = cal.get(Calendar.YEAR); + hour = cal.get(Calendar.HOUR_OF_DAY); + minute = cal.get(Calendar.MINUTE); + second = cal.get(Calendar.SECOND); + } + + /** + * Create a DateBuilder, with initial settings for the current date and time in the given timezone and locale. + */ + private DateBuilder(TimeZone tz, Locale lc) { + Calendar cal = Calendar.getInstance(tz, lc); + + this.tz = tz; + this.lc = lc; + month = cal.get(Calendar.MONTH) + 1; + day = cal.get(Calendar.DAY_OF_MONTH); + year = cal.get(Calendar.YEAR); + hour = cal.get(Calendar.HOUR_OF_DAY); + minute = cal.get(Calendar.MINUTE); + second = cal.get(Calendar.SECOND); + } + + /** + * Create a DateBuilder, with initial settings for the current date and time in the system default timezone. + */ + public static DateBuilder newDate() { + return new DateBuilder(); + } + + /** + * Create a DateBuilder, with initial settings for the current date and time in the given timezone. + */ + public static DateBuilder newDateInTimezone(TimeZone tz) { + return new DateBuilder(tz); + } + + /** + * Create a DateBuilder, with initial settings for the current date and time in the given locale. + */ + public static DateBuilder newDateInLocale(Locale lc) { + return new DateBuilder(lc); + } + + /** + * Create a DateBuilder, with initial settings for the current date and time in the given timezone and locale. + */ + public static DateBuilder newDateInTimeZoneAndLocale(TimeZone tz, Locale lc) { + return new DateBuilder(tz, lc); + } + + /** + * Build the Date defined by this builder instance. + */ + public Date build() { + Calendar cal; + + if(tz != null && lc != null) + cal = Calendar.getInstance(tz, lc); + else if(tz != null) + cal = Calendar.getInstance(tz); + else if(lc != null) + cal = Calendar.getInstance(lc); + else + cal = Calendar.getInstance(); + + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month - 1); + cal.set(Calendar.DAY_OF_MONTH, day); + cal.set(Calendar.HOUR_OF_DAY, hour); + cal.set(Calendar.MINUTE, minute); + cal.set(Calendar.SECOND, second); + cal.set(Calendar.MILLISECOND, 0); + + return cal.getTime(); + } + + /** + * Set the hour (0-23) for the Date that will be built by this builder. + */ + public DateBuilder atHourOfDay(int atHour) { + validateHour(atHour); + + this.hour = atHour; + return this; + } + + /** + * Set the minute (0-59) for the Date that will be built by this builder. + */ + public DateBuilder atMinute(int atMinute) { + validateMinute(atMinute); + + this.minute = atMinute; + return this; + } + + /** + * Set the second (0-59) for the Date that will be built by this builder, and truncate the milliseconds to 000. + */ + public DateBuilder atSecond(int atSecond) { + validateSecond(atSecond); + + this.second = atSecond; + return this; + } + + public DateBuilder atHourMinuteAndSecond(int atHour, int atMinute, int atSecond) { + validateHour(atHour); + validateMinute(atMinute); + validateSecond(atSecond); + + this.hour = atHour; + this.second = atSecond; + this.minute = atMinute; + return this; + } + + /** + * Set the day of month (1-31) for the Date that will be built by this builder. + */ + public DateBuilder onDay(int onDay) { + validateDayOfMonth(onDay); + + this.day = onDay; + return this; + } + + /** + * Set the month (1-12) for the Date that will be built by this builder. + */ + public DateBuilder inMonth(int inMonth) { + validateMonth(inMonth); + + this.month = inMonth; + return this; + } + + public DateBuilder inMonthOnDay(int inMonth, int onDay) { + validateMonth(inMonth); + validateDayOfMonth(onDay); + + this.month = inMonth; + this.day = onDay; + return this; + } + + /** + * Set the year for the Date that will be built by this builder. + */ + public DateBuilder inYear(int inYear) { + validateYear(inYear); + + this.year = inYear; + return this; + } + + /** + * Set the TimeZone for the Date that will be built by this builder (if "null", system default will be used) + */ + public DateBuilder inTimeZone(TimeZone timezone) { + this.tz = timezone; + return this; + } + + /** + * Set the Locale for the Date that will be built by this builder (if "null", system default will be used) + */ + public DateBuilder inLocale(Locale locale) { + this.lc = locale; + return this; + } + + public static Date futureDate(int interval, IntervalUnit unit) { + + Calendar c = Calendar.getInstance(); + c.setTime(new Date()); + c.setLenient(true); + + c.add(translate(unit), interval); + + return c.getTime(); + } + + + private static int translate(IntervalUnit unit) { + switch(unit) { + case DAY : return Calendar.DAY_OF_YEAR; + case HOUR : return Calendar.HOUR_OF_DAY; + case MINUTE : return Calendar.MINUTE; + case MONTH : return Calendar.MONTH; + case SECOND : return Calendar.SECOND; + case MILLISECOND : return Calendar.MILLISECOND; + case WEEK : return Calendar.WEEK_OF_YEAR; + case YEAR : return Calendar.YEAR; + default : throw new IllegalArgumentException("Unknown IntervalUnit"); + } + } + + /** + *+ * Get a
+ * + * @param second + * The value (0-59) to give the seconds field of the date + * @param minute + * The value (0-59) to give the minutes field of the date + * @param hour + * The value (0-23) to give the hours field of the date + * @return the new date + */ + public static Date tomorrowAt(int hour, int minute, int second) { + validateSecond(second); + validateMinute(minute); + validateHour(hour); + + Date date = new Date(); + + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.setLenient(true); + + // advance one day + c.add(Calendar.DAY_OF_YEAR, 1); + + c.set(Calendar.HOUR_OF_DAY, hour); + c.set(Calendar.MINUTE, minute); + c.set(Calendar.SECOND, second); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + + /** + *Date
object that represents the given time, on + * tomorrow's date. + *+ * Get a
+ * + * @param second + * The value (0-59) to give the seconds field of the date + * @param minute + * The value (0-59) to give the minutes field of the date + * @param hour + * The value (0-23) to give the hours field of the date + * @return the new date + */ + public static Date todayAt(int hour, int minute, int second) { + return dateOf(hour, minute, second); + } + + /** + *Date
object that represents the given time, on + * today's date (equivalent to {@link #dateOf(int, int, int)}). + *+ * Get a
+ * + * @param second + * The value (0-59) to give the seconds field of the date + * @param minute + * The value (0-59) to give the minutes field of the date + * @param hour + * The value (0-23) to give the hours field of the date + * @return the new date + */ + public static Date dateOf(int hour, int minute, int second) { + validateSecond(second); + validateMinute(minute); + validateHour(hour); + + Date date = new Date(); + + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.setLenient(true); + + c.set(Calendar.HOUR_OF_DAY, hour); + c.set(Calendar.MINUTE, minute); + c.set(Calendar.SECOND, second); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + + /** + *Date
object that represents the given time, on + * today's date (equivalent to {@link #todayAt(int, int, int)}). + *+ * Get a
+ * + * @param second + * The value (0-59) to give the seconds field of the date + * @param minute + * The value (0-59) to give the minutes field of the date + * @param hour + * The value (0-23) to give the hours field of the date + * @param dayOfMonth + * The value (1-31) to give the day of month field of the date + * @param month + * The value (1-12) to give the month field of the date + * @return the new date + */ + public static Date dateOf(int hour, int minute, int second, + int dayOfMonth, int month) { + validateSecond(second); + validateMinute(minute); + validateHour(hour); + validateDayOfMonth(dayOfMonth); + validateMonth(month); + + Date date = new Date(); + + Calendar c = Calendar.getInstance(); + c.setTime(date); + + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, dayOfMonth); + c.set(Calendar.HOUR_OF_DAY, hour); + c.set(Calendar.MINUTE, minute); + c.set(Calendar.SECOND, second); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + + /** + *Date
object that represents the given time, on the + * given date. + *+ * Get a
+ * + * @param second + * The value (0-59) to give the seconds field of the date + * @param minute + * The value (0-59) to give the minutes field of the date + * @param hour + * The value (0-23) to give the hours field of the date + * @param dayOfMonth + * The value (1-31) to give the day of month field of the date + * @param month + * The value (1-12) to give the month field of the date + * @param year + * The value (1970-2099) to give the year field of the date + * @return the new date + */ + public static Date dateOf(int hour, int minute, int second, + int dayOfMonth, int month, int year) { + validateSecond(second); + validateMinute(minute); + validateHour(hour); + validateDayOfMonth(dayOfMonth); + validateMonth(month); + validateYear(year); + + Date date = new Date(); + + Calendar c = Calendar.getInstance(); + c.setTime(date); + + c.set(Calendar.YEAR, year); + c.set(Calendar.MONTH, month - 1); + c.set(Calendar.DAY_OF_MONTH, dayOfMonth); + c.set(Calendar.HOUR_OF_DAY, hour); + c.set(Calendar.MINUTE, minute); + c.set(Calendar.SECOND, second); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + + + /** + *Date
object that represents the given time, on the + * given date. + *+ * Returns a date that is rounded to the next even hour after the current time. + *
+ * + *+ * For example a current time of 08:13:54 would result in a date + * with the time of 09:00:00. If the date's time is in the 23rd hour, the + * date's 'day' will be promoted, and the time will be set to 00:00:00. + *
+ * + * @return the new rounded date + */ + public static Date evenHourDateAfterNow() { + return evenHourDate(null); + } + /** + *+ * Returns a date that is rounded to the next even hour above the given + * date. + *
+ * + *+ * For example an input date with a time of 08:13:54 would result in a date + * with the time of 09:00:00. If the date's time is in the 23rd hour, the + * date's 'day' will be promoted, and the time will be set to 00:00:00. + *
+ * + * @param date + * the Date to round, ifnull
the current time will + * be used + * @return the new rounded date + */ + public static Date evenHourDate(Date date) { + if (date == null) { + date = new Date(); + } + + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.setLenient(true); + + c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY) + 1); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + + /** + *+ * Returns a date that is rounded to the previous even hour below the given + * date. + *
+ * + *+ * For example an input date with a time of 08:13:54 would result in a date + * with the time of 08:00:00. + *
+ * + * @param date + * the Date to round, ifnull
the current time will + * be used + * @return the new rounded date + */ + public static Date evenHourDateBefore(Date date) { + if (date == null) { + date = new Date(); + } + + Calendar c = Calendar.getInstance(); + c.setTime(date); + + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + + /** + *+ * Returns a date that is rounded to the next even minute after the current time. + *
+ * + *+ * For example a current time of 08:13:54 would result in a date + * with the time of 08:14:00. If the date's time is in the 59th minute, + * then the hour (and possibly the day) will be promoted. + *
+ * + * @return the new rounded date + */ + public static Date evenMinuteDateAfterNow() { + return evenMinuteDate(null); + } + + /** + *+ * Returns a date that is rounded to the next even minute above the given + * date. + *
+ * + *+ * For example an input date with a time of 08:13:54 would result in a date + * with the time of 08:14:00. If the date's time is in the 59th minute, + * then the hour (and possibly the day) will be promoted. + *
+ * + * @param date + * the Date to round, ifnull
the current time will + * be used + * @return the new rounded date + */ + public static Date evenMinuteDate(Date date) { + if (date == null) { + date = new Date(); + } + + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.setLenient(true); + + c.set(Calendar.MINUTE, c.get(Calendar.MINUTE) + 1); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + + /** + *+ * Returns a date that is rounded to the previous even minute below the + * given date. + *
+ * + *+ * For example an input date with a time of 08:13:54 would result in a date + * with the time of 08:13:00. + *
+ * + * @param date + * the Date to round, ifnull
the current time will + * be used + * @return the new rounded date + */ + public static Date evenMinuteDateBefore(Date date) { + if (date == null) { + date = new Date(); + } + + Calendar c = Calendar.getInstance(); + c.setTime(date); + + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + + /** + *+ * Returns a date that is rounded to the next even second after the current time. + *
+ * + * @return the new rounded date + */ + public static Date evenSecondDateAfterNow() { + return evenSecondDate(null); + } + /** + *+ * Returns a date that is rounded to the next even second above the given + * date. + *
+ * + * @param date + * the Date to round, ifnull
the current time will + * be used + * @return the new rounded date + */ + public static Date evenSecondDate(Date date) { + if (date == null) { + date = new Date(); + } + + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.setLenient(true); + + c.set(Calendar.SECOND, c.get(Calendar.SECOND) + 1); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + + /** + *+ * Returns a date that is rounded to the previous even second below the + * given date. + *
+ * + *+ * For example an input date with a time of 08:13:54.341 would result in a + * date with the time of 08:13:54.000. + *
+ * + * @param date + * the Date to round, ifnull
the current time will + * be used + * @return the new rounded date + */ + public static Date evenSecondDateBefore(Date date) { + if (date == null) { + date = new Date(); + } + + Calendar c = Calendar.getInstance(); + c.setTime(date); + + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + + /** + *+ * Returns a date that is rounded to the next even multiple of the given + * minute. + *
+ * + *+ * For example an input date with a time of 08:13:54, and an input + * minute-base of 5 would result in a date with the time of 08:15:00. The + * same input date with an input minute-base of 10 would result in a date + * with the time of 08:20:00. But a date with the time 08:53:31 and an + * input minute-base of 45 would result in 09:00:00, because the even-hour + * is the next 'base' for 45-minute intervals. + *
+ * + *+ * More examples:
+ *
+ * + * + * @param date + * the Date to round, if+ * + *Input Time + *Minute-Base + *Result Time + *+ * + *11:16:41 + *20 + *11:20:00 + *+ * + *11:36:41 + *20 + *11:40:00 + *+ * + *11:46:41 + *20 + *12:00:00 + *+ * + *11:26:41 + *30 + *11:30:00 + *+ * + *11:36:41 + *30 + *12:00:00 + *11:16:41 + *17 + *11:17:00 + * + * + *11:17:41 + *17 + *11:34:00 + * + * + *11:52:41 + *17 + *12:00:00 + * + * + *11:52:41 + *5 + *11:55:00 + * + * + *11:57:41 + *5 + *12:00:00 + * + * + *11:17:41 + *0 + *12:00:00 + * + * + *11:17:41 + *1 + *11:08:00 + * + *null
the current time will + * be used + * @param minuteBase + * the base-minute to set the time on + * @return the new rounded date + * + * @see #nextGivenSecondDate(Date, int) + */ + public static Date nextGivenMinuteDate(Date date, int minuteBase) { + if (minuteBase < 0 || minuteBase > 59) { + throw new IllegalArgumentException( + "minuteBase must be >=0 and <= 59"); + } + + if (date == null) { + date = new Date(); + } + + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.setLenient(true); + + if (minuteBase == 0) { + c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY) + 1); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + + int minute = c.get(Calendar.MINUTE); + + int arItr = minute / minuteBase; + + int nextMinuteOccurance = minuteBase * (arItr + 1); + + if (nextMinuteOccurance < 60) { + c.set(Calendar.MINUTE, nextMinuteOccurance); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } else { + c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY) + 1); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + } + + /** + *+ * Returns a date that is rounded to the next even multiple of the given + * minute. + *
+ * + *+ * The rules for calculating the second are the same as those for + * calculating the minute in the method + *
+ * + * @param date the Date to round, ifgetNextGivenMinuteDate(..)
. + *
null
the current time will + * be used + * @param secondBase the base-second to set the time on + * @return the new rounded date + * + * @see #nextGivenMinuteDate(Date, int) + */ + public static Date nextGivenSecondDate(Date date, int secondBase) { + if (secondBase < 0 || secondBase > 59) { + throw new IllegalArgumentException( + "secondBase must be >=0 and <= 59"); + } + + if (date == null) { + date = new Date(); + } + + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.setLenient(true); + + if (secondBase == 0) { + c.set(Calendar.MINUTE, c.get(Calendar.MINUTE) + 1); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + + int second = c.get(Calendar.SECOND); + + int arItr = second / secondBase; + + int nextSecondOccurance = secondBase * (arItr + 1); + + if (nextSecondOccurance < 60) { + c.set(Calendar.SECOND, nextSecondOccurance); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } else { + c.set(Calendar.MINUTE, c.get(Calendar.MINUTE) + 1); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + return c.getTime(); + } + } + + /** + * Translate a date & time from a users time zone to the another + * (probably server) time zone to assist in creating a simple trigger with + * the right date & time. + * + * @param date the date to translate + * @param src the original time-zone + * @param dest the destination time-zone + * @return the translated date + */ + public static Date translateTime(Date date, TimeZone src, TimeZone dest) { + + Date newDate = new Date(); + + int offset = (dest.getOffset(date.getTime()) - src.getOffset(date.getTime())); + + newDate.setTime(date.getTime() - offset); + + return newDate; + } + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + public static void validateDayOfWeek(int dayOfWeek) { + if (dayOfWeek < SUNDAY || dayOfWeek > SATURDAY) { + throw new IllegalArgumentException("Invalid day of week."); + } + } + + public static void validateHour(int hour) { + if (hour < 0 || hour > 23) { + throw new IllegalArgumentException( + "Invalid hour (must be >= 0 and <= 23)."); + } + } + + public static void validateMinute(int minute) { + if (minute < 0 || minute > 59) { + throw new IllegalArgumentException( + "Invalid minute (must be >= 0 and <= 59)."); + } + } + + public static void validateSecond(int second) { + if (second < 0 || second > 59) { + throw new IllegalArgumentException( + "Invalid second (must be >= 0 and <= 59)."); + } + } + + public static void validateDayOfMonth(int day) { + if (day < 1 || day > 31) { + throw new IllegalArgumentException("Invalid day of month."); + } + } + + public static void validateMonth(int month) { + if (month < 1 || month > 12) { + throw new IllegalArgumentException( + "Invalid month (must be >= 1 and <= 12."); + } + } + + private static final int MAX_YEAR = Calendar.getInstance().get(Calendar.YEAR) + 100; + public static void validateYear(int year) { + if (year < 0 || year > MAX_YEAR) { + throw new IllegalArgumentException( + "Invalid year (must be >= 0 and <= " + MAX_YEAR); + } + } + +} Index: 3rdParty_sources/quartz/org/quartz/DisallowConcurrentExecution.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/DisallowConcurrentExecution.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/DisallowConcurrentExecution.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,40 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An annotation that marks a {@link Job} class as one that must not have multiple + * instances executed concurrently (where instance is based-upon a {@link JobDetail} + * definition - or in other words based upon a {@link JobKey}). + * + * @see PersistJobDataAfterExecution + * + * @author jhouse + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface DisallowConcurrentExecution { + +} Index: 3rdParty_sources/quartz/org/quartz/ExecuteInJTATransaction.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/ExecuteInJTATransaction.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/ExecuteInJTATransaction.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,62 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.transaction.UserTransaction; + +/** + * An annotation that marks a {@link Job} class as one that will have its + * execution wrapped by a JTA Transaction. + * + *If this annotation is present, Quartz will begin a JTA transaction + * before calling the
+ * + *execute()
method, and will commit + * the transaction if the method does not throw an exception and the + * transaction has not hadsetRollbackOnly()
called on it + * (otherwise the transaction will be rolled-back by Quartz).This is essentially the same behavior as setting the configuration + * property
+ * + * @author jhouse + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface ExecuteInJTATransaction { + + /** + * The JTA transaction timeout. + *org.quartz.scheduler.wrapJobExecutionInUserTransaction
+ * totrue
- except that it only affects the job that has + * the annotation, rather than all jobs (as the property does). If the + * property is set totrue
and the annotation is also set, + * then of course the annotation becomes redundant.+ * If set then the {@code UserTransaction} timeout will be set to this + * value before beginning the transaction. + * + * @see UserTransaction#setTransactionTimeout(int) + * @return the transaction timeout. + */ + int timeout() default -1; +} Index: 3rdParty_sources/quartz/org/quartz/InterruptableJob.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/InterruptableJob.java (.../InterruptableJob.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/InterruptableJob.java (.../InterruptableJob.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,19 +16,17 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; /** - *
* The interface to be implemented by
* + *{@link Job}s
that provide a - * mechanism for having their execution interrupted. It is NOT a requirment + * mechanism for having their execution interrupted. It is NOT a requirement * for jobs to implement this interface - in fact, for most people, none of * their jobs will. - *Interrupting a
Job
is very analogous in concept and + * challenge to normal interruption of aThread
in Java. + * ** The means of actually interrupting the Job must be implemented within the *
* + *Job
itself (theinterrupt()
method of this @@ -51,18 +49,22 @@ * If the Job performs some form of blocking I/O or similar functions, you may * want to consider having theJob.execute(..)
method store a * reference to the callingThread
as a member variable. Then the - * impplementation of this interfacesinterrupt()
method can call + * Implementation of this interfacesinterrupt()
method can call *interrupt()
on that Thread. Before attempting this, make * sure that you fully understand whatjava.lang.Thread.interrupt()
* does and doesn't do. Also make sure that you clear the Job's member - * reference to the Thread when the execute(..) method exits (preferrably in a + * reference to the Thread when the execute(..) method exits (preferably in a *finally
block. *+ * See Example 7 (org.quartz.examples.example7.DumbInterruptableJob) for a simple + * implementation demonstration. + *
* @see Job * @see StatefulJob - * @see Scheduler#interrupt(String, String) - * @see org.quartz.examples.example7.DumbInterruptableJob + * @see Scheduler#interrupt(JobKey) + * @see Scheduler#interrupt(String) * * @author James House */ @@ -82,12 +84,9 @@ * interrupts theJob
. * * - * @return void (nothing) if job interrupt is successful. * @throws UnableToInterruptJobException * if there is an exception while interrupting the job. */ - public void interrupt() - throws UnableToInterruptJobException; - - + void interrupt() + throws UnableToInterruptJobException; } Index: 3rdParty_sources/quartz/org/quartz/Job.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/Job.java (.../Job.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/Job.java (.../Job.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,9 +16,6 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; /** @@ -38,7 +35,10 @@ * * * @see JobDetail - * @see StatefulJob + * @see JobBuilder + * @see ExecuteInJTATransaction + * @see DisallowConcurrentExecution + * @see PersistJobDataAfterExecution * @see Trigger * @see Scheduler * @@ -70,11 +70,10 @@ * execution. * * - * @return void (nothing) if job is successful. * @throws JobExecutionException * if there is an exception while executing the job. */ - public void execute(JobExecutionContext context) - throws JobExecutionException; + void execute(JobExecutionContext context) + throws JobExecutionException; } Index: 3rdParty_sources/quartz/org/quartz/JobBuilder.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/JobBuilder.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/JobBuilder.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,351 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import org.quartz.impl.JobDetailImpl; +import org.quartz.utils.Key; + +/** + *JobBuilder
is used to instantiate {@link JobDetail}s. + * + *The builder will always try to keep itself in a valid state, with + * reasonable defaults set for calling build() at any point. For instance + * if you do not invoke withIdentity(..) a job name will be generated + * for you.
+ * + *Quartz provides a builder-style API for constructing scheduling-related + * entities via a Domain-Specific Language (DSL). The DSL can best be + * utilized through the usage of static imports of the methods on the classes + *
+ * + *TriggerBuilder
,JobBuilder
, + *DateBuilder
,JobKey
,TriggerKey
+ * and the variousScheduleBuilder
implementations.Client code can then use the DSL to write code such as this:
+ *+ * JobDetail job = newJob(MyJob.class) + * .withIdentity("myJob") + * .build(); + * + * Trigger trigger = newTrigger() + * .withIdentity(triggerKey("myTrigger", "myTriggerGroup")) + * .withSchedule(simpleSchedule() + * .withIntervalInHours(1) + * .repeatForever()) + * .startAt(futureDate(10, MINUTES)) + * .build(); + * + * scheduler.scheduleJob(job, trigger); + *+ * + * @see TriggerBuilder + * @see DateBuilder + * @see JobDetail + */ +public class JobBuilder { + + private JobKey key; + private String description; + private Class extends Job> jobClass; + private boolean durability; + private boolean shouldRecover; + + private JobDataMap jobDataMap = new JobDataMap(); + + protected JobBuilder() { + } + + /** + * Create a JobBuilder with which to define aJobDetail
. + * + * @return a new JobBuilder + */ + public static JobBuilder newJob() { + return new JobBuilder(); + } + + /** + * Create a JobBuilder with which to define aJobDetail
, + * and set the class name of theJob
to be executed. + * + * @return a new JobBuilder + */ + public static JobBuilder newJob(Class extends Job> jobClass) { + JobBuilder b = new JobBuilder(); + b.ofType(jobClass); + return b; + } + + /** + * Produce theJobDetail
instance defined by this + *JobBuilder
. + * + * @return the defined JobDetail. + */ + public JobDetail build() { + + JobDetailImpl job = new JobDetailImpl(); + + job.setJobClass(jobClass); + job.setDescription(description); + if(key == null) + key = new JobKey(Key.createUniqueName(null), null); + job.setKey(key); + job.setDurability(durability); + job.setRequestsRecovery(shouldRecover); + + + if(!jobDataMap.isEmpty()) + job.setJobDataMap(jobDataMap); + + return job; + } + + /** + * Use aJobKey
with the given name and default group to + * identify the JobDetail. + * + *If none of the 'withIdentity' methods are set on the JobBuilder, + * then a random, unique JobKey will be generated.
+ * + * @param name the name element for the Job's JobKey + * @return the updated JobBuilder + * @see JobKey + * @see JobDetail#getKey() + */ + public JobBuilder withIdentity(String name) { + key = new JobKey(name, null); + return this; + } + + /** + * Use aJobKey
with the given name and group to + * identify the JobDetail. + * + *If none of the 'withIdentity' methods are set on the JobBuilder, + * then a random, unique JobKey will be generated.
+ * + * @param name the name element for the Job's JobKey + * @param group the group element for the Job's JobKey + * @return the updated JobBuilder + * @see JobKey + * @see JobDetail#getKey() + */ + public JobBuilder withIdentity(String name, String group) { + key = new JobKey(name, group); + return this; + } + + /** + * Use aJobKey
to identify the JobDetail. + * + *If none of the 'withIdentity' methods are set on the JobBuilder, + * then a random, unique JobKey will be generated.
+ * + * @param jobKey the Job's JobKey + * @return the updated JobBuilder + * @see JobKey + * @see JobDetail#getKey() + */ + public JobBuilder withIdentity(JobKey jobKey) { + this.key = jobKey; + return this; + } + + /** + * Set the given (human-meaningful) description of the Job. + * + * @param jobDescription the description for the Job + * @return the updated JobBuilder + * @see JobDetail#getDescription() + */ + public JobBuilder withDescription(String jobDescription) { + this.description = jobDescription; + return this; + } + + /** + * Set the class which will be instantiated and executed when a + * Trigger fires that is associated with this JobDetail. + * + * @param jobClazz a class implementing the Job interface. + * @return the updated JobBuilder + * @see JobDetail#getJobClass() + */ + public JobBuilder ofType(Class extends Job> jobClazz) { + this.jobClass = jobClazz; + return this; + } + + /** + * Instructs theScheduler
whether or not theJob
+ * should be re-executed if a 'recovery' or 'fail-over' situation is + * encountered. + * + *+ * If not explicitly set, the default value is
+ * + * @return the updated JobBuilder + * @see JobDetail#requestsRecovery() + */ + public JobBuilder requestRecovery() { + this.shouldRecover = true; + return this; + } + + /** + * Instructs thefalse
. + *Scheduler
whether or not theJob
+ * should be re-executed if a 'recovery' or 'fail-over' situation is + * encountered. + * + *+ * If not explicitly set, the default value is
+ * + * @param jobShouldRecover the desired setting + * @return the updated JobBuilder + */ + public JobBuilder requestRecovery(boolean jobShouldRecover) { + this.shouldRecover = jobShouldRecover; + return this; + } + + /** + * Whether or not thefalse
. + *Job
should remain stored after it is + * orphaned (no{@link Trigger}s
point to it). + * + *+ * If not explicitly set, the default value is
+ * + * @return the updated JobBuilder + * @see JobDetail#isDurable() + */ + public JobBuilder storeDurably() { + this.durability = true; + return this; + } + + /** + * Whether or not thefalse
+ * - this method sets the value totrue
. + *Job
should remain stored after it is + * orphaned (no{@link Trigger}s
point to it). + * + *+ * If not explicitly set, the default value is
+ * + * @param jobDurability the value to set for the durability property. + * @return the updated JobBuilder + * @see JobDetail#isDurable() + */ + public JobBuilder storeDurably(boolean jobDurability) { + this.durability = jobDurability; + return this; + } + + /** + * Add the given key-value pair to the JobDetail's {@link JobDataMap}. + * + * @return the updated JobBuilder + * @see JobDetail#getJobDataMap() + */ + public JobBuilder usingJobData(String dataKey, String value) { + jobDataMap.put(dataKey, value); + return this; + } + + /** + * Add the given key-value pair to the JobDetail's {@link JobDataMap}. + * + * @return the updated JobBuilder + * @see JobDetail#getJobDataMap() + */ + public JobBuilder usingJobData(String dataKey, Integer value) { + jobDataMap.put(dataKey, value); + return this; + } + + /** + * Add the given key-value pair to the JobDetail's {@link JobDataMap}. + * + * @return the updated JobBuilder + * @see JobDetail#getJobDataMap() + */ + public JobBuilder usingJobData(String dataKey, Long value) { + jobDataMap.put(dataKey, value); + return this; + } + + /** + * Add the given key-value pair to the JobDetail's {@link JobDataMap}. + * + * @return the updated JobBuilder + * @see JobDetail#getJobDataMap() + */ + public JobBuilder usingJobData(String dataKey, Float value) { + jobDataMap.put(dataKey, value); + return this; + } + + /** + * Add the given key-value pair to the JobDetail's {@link JobDataMap}. + * + * @return the updated JobBuilder + * @see JobDetail#getJobDataMap() + */ + public JobBuilder usingJobData(String dataKey, Double value) { + jobDataMap.put(dataKey, value); + return this; + } + + /** + * Add the given key-value pair to the JobDetail's {@link JobDataMap}. + * + * @return the updated JobBuilder + * @see JobDetail#getJobDataMap() + */ + public JobBuilder usingJobData(String dataKey, Boolean value) { + jobDataMap.put(dataKey, value); + return this; + } + + /** + * Add all the data from the given {@link JobDataMap} to the + * {@code JobDetail}'s {@code JobDataMap}. + * + * @return the updated JobBuilder + * @see JobDetail#getJobDataMap() + */ + public JobBuilder usingJobData(JobDataMap newJobDataMap) { + jobDataMap.putAll(newJobDataMap); + return this; + } + + /** + * Replace the {@code JobDetail}'s {@link JobDataMap} with the + * given {@code JobDataMap}. + * + * @return the updated JobBuilder + * @see JobDetail#getJobDataMap() + */ + public JobBuilder setJobData(JobDataMap newJobDataMap) { + jobDataMap = newJobDataMap; + return this; + } +} Index: 3rdParty_sources/quartz/org/quartz/JobDataMap.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/JobDataMap.java (.../JobDataMap.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/JobDataMap.java (.../JobDataMap.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,26 +16,20 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; import java.io.Serializable; -import java.util.Iterator; import java.util.Map; -import org.quartz.utils.DirtyFlagMap; +import org.quartz.utils.StringKeyDirtyFlagMap; /** - *false
. + ** Holds state information for
* *Job
instances. - **
* *JobDataMap
instances are stored once when theJob
* is added to a scheduler. They are also re-persisted after every execution of - *StatefulJob
instances. + * jobs annotated with@PersistJobDataAfterExecution
. *@@ -54,13 +48,13 @@ *
* * @see Job - * @see StatefulJob + * @see PersistJobDataAfterExecution * @see Trigger * @see JobExecutionContext * * @author James House */ -public class JobDataMap extends DirtyFlagMap implements Serializable { +public class JobDataMap extends StringKeyDirtyFlagMap implements Serializable { private static final long serialVersionUID = -6939901990106713909L; @@ -72,16 +66,6 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - private boolean allowsTransientData = false; - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Constructors. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - /** ** Create an empty
*/ - public JobDataMap(Map map) { + public JobDataMap(Map, ?> map) { this(); - - putAll(map); + @SuppressWarnings("unchecked") // casting to keep API compatible and avoid compiler errors/warnings. + MapJobDataMap
. @@ -96,10 +80,11 @@ * Create aJobDataMap
with the given data. *mapTyped = (Map )map; + putAll(mapTyped); } /* @@ -112,163 +97,12 @@ /** * - * Tell the
- * - *JobDataMap
that it should allow non-Serializable
- * data. - *- * If the
- */ - public void setAllowsTransientData(boolean allowsTransientData) { - - if (containsTransientData() && !allowsTransientData) - throw new IllegalStateException( - "Cannot set property 'allowsTransientData' to 'false' " - + "when data map contains non-serializable objects."); - - this.allowsTransientData = allowsTransientData; - } - - public boolean getAllowsTransientData() { - return allowsTransientData; - } - - public boolean containsTransientData() { - - if (!getAllowsTransientData()) // short circuit... - return false; - - String[] keys = getKeys(); - - for (int i = 0; i < keys.length; i++) { - Object o = super.get(keys[i]); - if (!(o instanceof Serializable)) return true; - } - - return false; - } - - /** - *JobDataMap
does contain non-Serializable
- * objects, and it belongs to a non-volatileJob
that is - * stored in aJobStore
that supports persistence, then - * those elements will be nulled-out during persistence. - *- * Nulls-out any data values that are non-Serializable. - *
- */ - public void removeTransientData() { - - if (!getAllowsTransientData()) // short circuit... - return; - - String[] keys = getKeys(); - - for (int i = 0; i < keys.length; i++) { - Object o = super.get(keys[i]); - if (!(o instanceof Serializable)) remove(keys[i]); - } - - } - - /** - *- * Adds the name-value pairs in the given
- * - *Map
to theJobDataMap
. - *- * All keys must be
- */ - public void putAll(Map map) { - Iterator itr = map.keySet().iterator(); - while (itr.hasNext()) { - Object key = itr.next(); - Object val = map.get(key); - - put(key, val); - // will throw IllegalArgumentException if value not serilizable - } - } - - /** - *String
s, and all values must beSerializable
. - *- * Adds the given
- */ - public void put(String key, int value) { - super.put(key, new Integer(value)); - } - - /** - *int
value to theJob
's - * data map. - *- * Adds the given
- */ - public void put(String key, long value) { - super.put(key, new Long(value)); - } - - /** - *long
value to theJob
's - * data map. - *- * Adds the given
- */ - public void put(String key, float value) { - super.put(key, new Float(value)); - } - - /** - *float
value to theJob
's - * data map. - *- * Adds the given
- */ - public void put(String key, double value) { - super.put(key, new Double(value)); - } - - /** - *double
value to theJob
's - * data map. - *- * Adds the given
- */ - public void put(String key, boolean value) { - super.put(key, new Boolean(value)); - } - - /** - *boolean
value to theJob
's - * data map. - *- * Adds the given
- */ - public void put(String key, char value) { - super.put(key, new Character(value)); - } - - /** - *char
value to theJob
's - * data map. - *- * Adds the given
- */ - public void put(String key, String value) { - super.put(key, value); - } - - /** - *String
value to theJob
's - * data map. - ** Adds the given
*/ public void putAsString(String key, boolean value) { - String strValue = new Boolean(value).toString(); + String strValue = Boolean.valueOf(value).toString(); super.put(key, strValue); } @@ -292,7 +126,7 @@ * */ public void putAsString(String key, char value) { - String strValue = new Character(value).toString(); + String strValue = Character.valueOf(value).toString(); super.put(key, strValue); } @@ -316,7 +150,7 @@ * */ public void putAsString(String key, double value) { - String strValue = new Double(value).toString(); + String strValue = Double.toString(value); super.put(key, strValue); } @@ -340,7 +174,7 @@ * */ public void putAsString(String key, float value) { - String strValue = new Float(value).toString(); + String strValue = Float.toString(value); super.put(key, strValue); } @@ -364,7 +198,7 @@ * */ public void putAsString(String key, int value) { - String strValue = new Integer(value).toString(); + String strValue = Integer.valueOf(value).toString(); super.put(key, strValue); } @@ -388,7 +222,7 @@ * */ public void putAsString(String key, long value) { - String strValue = new Long(value).toString(); + String strValue = Long.valueOf(value).toString(); super.put(key, strValue); } @@ -407,156 +241,16 @@ /** *boolean
value as a string version to the *Job
's data map. *- * Adds the given
- */ - public Object put(Object key, Object value) { - if (!(key instanceof String)) - throw new IllegalArgumentException( - "Keys in map must be Strings."); - - return super.put(key, value); - } - - /** - *Serializable
object value to theJobDataMap
. - ** Retrieve the identified
* * @throws ClassCastException - * if the identified object is not an Integer. - */ - public int getInt(String key) { - Object obj = get(key); - - try { - return ((Integer) obj).intValue(); - } catch (Exception e) { - throw new ClassCastException("Identified object is not an Integer."); - } - } - - /** - *int
value from theJobDataMap
. *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not a Long. - */ - public long getLong(String key) { - Object obj = get(key); - - try { - return ((Long) obj).longValue(); - } catch (Exception e) { - throw new ClassCastException("Identified object is not a Long."); - } - } - - /** - *long
value from theJobDataMap
. - *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not a Float. - */ - public float getFloat(String key) { - Object obj = get(key); - - try { - return ((Float) obj).floatValue(); - } catch (Exception e) { - throw new ClassCastException("Identified object is not a Float."); - } - } - - /** - *float
value from theJobDataMap
. - *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not a Double. - */ - public double getDouble(String key) { - Object obj = get(key); - - try { - return ((Double) obj).doubleValue(); - } catch (Exception e) { - throw new ClassCastException("Identified object is not a Double."); - } - } - - /** - *double
value from theJobDataMap
. - *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not a Boolean. - */ - public boolean getBoolean(String key) { - Object obj = get(key); - - try { - return ((Boolean) obj).booleanValue(); - } catch (Exception e) { - throw new ClassCastException("Identified object is not a Boolean."); - } - } - - /** - *boolean
value from theJobDataMap
. - *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not a Character. - */ - public char getChar(String key) { - Object obj = get(key); - - try { - return ((Character) obj).charValue(); - } catch (Exception e) { - throw new ClassCastException( - "Identified object is not a Character."); - } - } - - /** - *char
value from theJobDataMap
. - *- * Retrieve the identified
- * - * @throws ClassCastException * if the identified object is not a String. */ - public String getString(String key) { - Object obj = get(key); - - try { - return (String) obj; - } catch (Exception e) { - throw new ClassCastException("Identified object is not a String."); - } - } - - /** - *String
value from theJobDataMap
. - *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not a String. - */ public int getIntFromString(String key) { Object obj = get(key); - return new Integer((String) obj).intValue(); + return new Integer((String) obj); } /** @@ -565,15 +259,16 @@ * * * @throws ClassCastException - * if the identified object is not a String or Integeger. + * if the identified object is not a String or Integer. */ - public long getIntValue(String key) { + public int getIntValue(String key) { Object obj = get(key); - if(obj instanceof String) + if(obj instanceof String) { return getIntFromString(key); - else + } else { return getInt(key); + } } /** @@ -601,7 +296,7 @@ public boolean getBooleanValueFromString(String key) { Object obj = get(key); - return new Boolean((String) obj).booleanValue(); + return Boolean.valueOf((String) obj); } /** @@ -616,10 +311,11 @@ public boolean getBooleanValue(String key) { Object obj = get(key); - if(obj instanceof String) + if(obj instanceof String) { return getBooleanValueFromString(key); - else + } else { return getBoolean(key); + } } /** @@ -633,7 +329,7 @@ public Boolean getBooleanFromString(String key) { Object obj = get(key); - return new Boolean((String) obj); + return Boolean.valueOf((String) obj); } /** @@ -661,7 +357,7 @@ public Character getCharacterFromString(String key) { Object obj = get(key); - return new Character(((String) obj).charAt(0)); + return ((String) obj).charAt(0); } /** @@ -675,7 +371,7 @@ public double getDoubleValueFromString(String key) { Object obj = get(key); - return new Double((String) obj).doubleValue(); + return Double.valueOf((String) obj); } /** @@ -689,10 +385,11 @@ public double getDoubleValue(String key) { Object obj = get(key); - if(obj instanceof String) + if(obj instanceof String) { return getDoubleValueFromString(key); - else + } else { return getDouble(key); + } } /** @@ -720,7 +417,7 @@ public float getFloatValueFromString(String key) { Object obj = get(key); - return new Float((String) obj).floatValue(); + return new Float((String) obj); } /** @@ -734,10 +431,11 @@ public float getFloatValue(String key) { Object obj = get(key); - if(obj instanceof String) + if(obj instanceof String) { return getFloatValueFromString(key); - else + } else { return getFloat(key); + } } /** @@ -765,7 +463,7 @@ public long getLongValueFromString(String key) { Object obj = get(key); - return new Long((String) obj).longValue(); + return new Long((String) obj); } /** @@ -779,10 +477,11 @@ public long getLongValue(String key) { Object obj = get(key); - if(obj instanceof String) + if(obj instanceof String) { return getLongValueFromString(key); - else + } else { return getLong(key); + } } /** @@ -798,9 +497,4 @@ return new Long((String) obj); } - - public String[] getKeys() { - return (String[]) keySet().toArray(new String[size()]); - } - } Index: 3rdParty_sources/quartz/org/quartz/JobDetail.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/JobDetail.java (.../JobDetail.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/JobDetail.java (.../JobDetail.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,5 @@ - -/* - * Copyright 2004-2005 OpenSymphony +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,364 +15,67 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; -import java.util.ArrayList; +import java.io.Serializable; /** - *int
value from theJobDataMap
. - *- * Conveys the detail properties of a given
+ * Conveys the detail properties of a givenJob
instance. - *Job
instance. JobDetails are + * to be created/defined with {@link JobBuilder}. * ** Quartz does not store an actual instance of a
* *Job
class, but * instead allows you to define an instance of one, through the use of aJobDetail
. *- *
* *Job
s have a name and group associated with them, which + *Job
s have a name and group associated with them, which * should uniquely identify them within a single{@link Scheduler}
. *- *
* + * @see JobBuilder * @see Job - * @see StatefulJob * @see JobDataMap * @see Trigger * * @author James House - * @author Sharada Jambula */ -public class JobDetail implements Cloneable, java.io.Serializable { +public interface JobDetail extends Serializable, Cloneable { - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Data members. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ + public JobKey getKey(); - private String name; - - private String group = Scheduler.DEFAULT_GROUP; - - private String description; - - private Class jobClass; - - private JobDataMap jobDataMap; - - private boolean volatility = false; - - private boolean durability = false; - - private boolean shouldRecover = false; - - private ArrayList jobListeners = new ArrayList(2); - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Constructors. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - /** *Trigger
s are the 'mechanism' by whichJob
s - * are scheduled. ManyTrigger
s can point to the sameJob
, + *Trigger
s are the 'mechanism' by whichJob
s + * are scheduled. ManyTrigger
s can point to the sameJob
, * but a singleTrigger
can only point to oneJob
. *- * Create a
- * - *JobDetail
with no specified name or group, and - * the default settings of all the other properties. - *- * Note that the {@link #setName(String)},{@link #setGroup(String)}and - * {@link #setJobClass(Class)}methods must be called before the job can be - * placed into a {@link Scheduler} - *
- */ - public JobDetail() { - // do nothing... - } - - /** - *- * Create a
- * - * @param group ifJobDetail
with the given name, and group, and - * the default settings of all the other properties. - *null
, Scheduler.DEFAULT_GROUP will be used. - * - * @exception IllegalArgumentException - * if nameis null or empty, or the group is an empty string. - */ - public JobDetail(String name, String group, Class jobClass) { - setName(name); - setGroup(group); - setJobClass(jobClass); - } - - /** - *- * Create a
- * - * @param group ifJobDetail
with the given name, and group, and - * the given settings of all the other properties. - *null
, Scheduler.DEFAULT_GROUP will be used. - * - * @exception IllegalArgumentException - * if nameis null or empty, or the group is an empty string. - */ - public JobDetail(String name, String group, Class jobClass, - boolean volatility, boolean durability, boolean recover) { - setName(name); - setGroup(group); - setJobClass(jobClass); - setVolatility(volatility); - setDurability(durability); - setRequestsRecovery(recover); - } - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Interface. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - - /** - *- * Get the name of this
- */ - public String getName() { - return name; - } - - /** - *Job
. - *- * Set the name of this
- * - * @exception IllegalArgumentException - * if name is null or empty. - */ - public void setName(String name) { - if (name == null || name.trim().length() == 0) - throw new IllegalArgumentException("Job name cannot be empty."); - - this.name = name; - } - - /** - *Job
. - *- * Get the group of this
- */ - public String getGroup() { - return group; - } - - /** - *Job
. - *- * Set the group of this
- * - * @param group ifJob
. - *null
, Scheduler.DEFAULT_GROUP will be used. - * - * @exception IllegalArgumentException - * if the group is an empty string. - */ - public void setGroup(String group) { - if (group != null && group.trim().length() == 0) - throw new IllegalArgumentException( - "Group name cannot be empty."); - - if(group == null) - group = Scheduler.DEFAULT_GROUP; - - this.group = group; - } - - /** - *- * Returns the 'full name' of the
- */ - public String getFullName() { - return group + "." + name; - } - - /** - *Trigger
in the format - * "group.name". - ** Return the description given to the
* * @return null if no description was set. */ - public String getDescription() { - return description; - } + public String getDescription(); /** *Job
instance by its * creator (if any). *- * Set a description for the
- */ - public void setDescription(String description) { - this.description = description; - } - - /** - *Job
instance - may be useful - * for remembering/displaying the purpose of the job, though the - * description has no meaning to Quartz. - ** Get the instance of
*/ - public Class getJobClass() { - return jobClass; - } + public Class extends Job> getJobClass(); /** *Job
that will be executed. *- * Set the instance of
- * - * @exception IllegalArgumentException - * if jobClass is null or the class is not aJob
that will be executed. - *Job
. - */ - public void setJobClass(Class jobClass) { - if (jobClass == null) - throw new IllegalArgumentException("Job class cannot be null."); - - if (!Job.class.isAssignableFrom(jobClass)) - throw new IllegalArgumentException( - "Job class must implement the Job interface."); - - this.jobClass = jobClass; - } - - /** - ** Get the
*/ - public JobDataMap getJobDataMap() { - if (jobDataMap == null) jobDataMap = new JobDataMap(); - return jobDataMap; - } + public JobDataMap getJobDataMap(); /** *JobDataMap
that is associated with theJob
. *- * Set the
- */ - public void setJobDataMap(JobDataMap jobDataMap) { - this.jobDataMap = jobDataMap; - } - - /** - *JobDataMap
to be associated with theJob
. - *- * Validates whether the properties of the
JobDetail
are - * valid for submission into aScheduler
. - * - * @throws IllegalStateException - * if a required property (such as Name, Group, Class) is not - * set. - */ - public void validate() throws SchedulerException { - if (name == null) - throw new SchedulerException("Job's name cannot be null", - SchedulerException.ERR_CLIENT_ERROR); - - if (group == null) - throw new SchedulerException("Job's group cannot be null", - SchedulerException.ERR_CLIENT_ERROR); - - if (jobClass == null) - throw new SchedulerException("Job's class cannot be null", - SchedulerException.ERR_CLIENT_ERROR); - } - - /** - *- * Set whether or not the
- * - *Job
should be persisted in the - *{@link org.quartz.spi.JobStore}
for re-use after program - * restarts. - *- * If not explicitly set, the default value is
- */ - public void setVolatility(boolean volatility) { - this.volatility = volatility; - } - - /** - *false
. - *- * Set whether or not the
- * - *Job
should remain stored after it - * is orphaned (no{@link Trigger}s
point to it). - *- * If not explicitly set, the default value is
- */ - public void setDurability(boolean durability) { - this.durability = durability; - } - - /** - *false
. - *- * Set whether or not the the
- * - *Scheduler
should re-execute - * theJob
if a 'recovery' or 'fail-over' situation is - * encountered. - *- * If not explicitly set, the default value is
- * - * @see JobExecutionContext#isRecovering() - * @see JobExecutionContext#isFailedOver() - */ - public void setRequestsRecovery(boolean shouldRecover) { - this.shouldRecover = shouldRecover; - } - - /** - *false
. - *- * Whether or not the
- * - *Job
should not be persisted in the - *{@link org.quartz.spi.JobStore}
for re-use after program - * restarts. - *- * If not explicitly set, the default value is
- * - * @returnfalse
. - *true
if theJob
should be garbage - * collected along with the{@link Scheduler}
. - */ - public boolean isVolatile() { - return volatility; - } - - /** - ** Whether or not the
@@ -385,21 +87,19 @@ * @returnJob
should remain stored after it is * orphaned (no{@link Trigger}s
point to it). *true
if the Job should remain persisted after * being orphaned. */ - public boolean isDurable() { - return durability; - } + public boolean isDurable(); /** - *- * Whether or not the
+ * @see PersistJobDataAfterExecution + * @return whether the associated Job class carries the {@link PersistJobDataAfterExecution} annotation. */ - public boolean isStateful() { - if (jobClass == null) - return false; + public boolean isPersistJobDataAfterExecution(); - return (StatefulJob.class.isAssignableFrom(jobClass)); - } + /** + * @see DisallowConcurrentExecution + * @return whether the associated Job class carries the {@link DisallowConcurrentExecution} annotation. + */ + public boolean isConcurrentExectionDisallowed(); /** *Job
implements the interface{@link StatefulJob}
. - *@@ -413,70 +113,15 @@ *
* * @see JobExecutionContext#isRecovering() - * @see JobExecutionContext#isFailedOver() */ - public boolean requestsRecovery() { - return shouldRecover; - } + public boolean requestsRecovery(); + public Object clone(); + /** - *- * Add the specified name of a
+ * Get a {@link JobBuilder} that is configured to produce a + *{@link JobListener}
to the - * end of theJob
's list of listeners. - *JobDetail
identical to this one. */ - public void addJobListener(String name) { - jobListeners.add(name); - } + public JobBuilder getJobBuilder(); - /** - *- * Remove the specified name of a
- * - * @return true if the given name was found in the list, and removed - */ - public boolean removeJobListener(String name) { - return jobListeners.remove(name); - } - - /** - *{@link JobListener}
from - * theJob
's list of listeners. - *- * Returns an array of
- */ - public String[] getJobListenerNames() { - return (String[]) jobListeners.toArray(new String[jobListeners.size()]); - } - - /** - *String
s containing the names of all - *{@link JobListener}
s assigned to theJob
, - * in the order in which they should be notified. - *- * Return a simple string representation of this object. - *
- */ - public String toString() { - return "JobDetail '" + getFullName() + "': jobClass: '" - + ((getJobClass() == null) ? null : getJobClass().getName()) - + " isStateful: " + isStateful() + " isVolatile: " - + isVolatile() + " isDurable: " + isDurable() - + " requestsRecovers: " + requestsRecovery(); - } - - public Object clone() { - JobDetail copy; - try { - copy = (JobDetail) super.clone(); - copy.jobListeners = (ArrayList) jobListeners.clone(); - if (jobDataMap != null) - copy.jobDataMap = (JobDataMap) jobDataMap.clone(); - } catch (CloneNotSupportedException ex) { - throw new IncompatibleClassChangeError("Not Cloneable."); - } - - return copy; - } - -} +} \ No newline at end of file Index: 3rdParty_sources/quartz/org/quartz/JobExecutionContext.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/JobExecutionContext.java (.../JobExecutionContext.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/JobExecutionContext.java (.../JobExecutionContext.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,5 @@ - -/* - * Copyright 2004-2005 OpenSymphony +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,23 +15,15 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; import java.util.Date; -import java.util.HashMap; -import org.quartz.spi.TriggerFiredBundle; - /** - ** A context bundle containing handles to various environment information, that * is given to a
* *{@link org.quartz.JobDetail}
instance as it is * executed, and to a{@link Trigger}
instance after the * execution completes. - ** The
* *JobDataMap
found on this object (via the @@ -43,13 +34,14 @@ * It is thus considered a 'best practice' that the execute code of a Job * retrieve data from the JobDataMap found on this object NOTE: Do not * expect value 'set' into this JobDataMap to somehow be set back onto a - *StatefulJob
's own JobDataMap. + * job's own JobDataMap - even if it has the + *@PersistJobDataAfterExecution
annotation. **
* - * @see #getJobDetail() * @see #getScheduler() * @see #getMergedJobDataMap() + * @see #getJobDetail() * * @see Job * @see Trigger * @see JobDataMap * * @author James House */ -public class JobExecutionContext implements java.io.Serializable { +public interface JobExecutionContext { - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Data members. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - - private transient Scheduler scheduler; - - private Trigger trigger; - - private JobDetail jobDetail; - - private JobDataMap jobDataMap; - - private transient Job job; - - private Calendar calendar; - - private boolean recovering = false; - - private int numRefires = 0; - - private Date fireTime; - - private Date scheduledFireTime; - - private Date prevFireTime; - - private Date nextFireTime; - - private long jobRunTime = -1; - - private Object result; - - private HashMap data = new HashMap(); - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Constructors. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - /** *JobExecutionContext
s are also returned from the *Scheduler.getCurrentlyExecutingJobs()
- * method. These are the same instances as those past into the jobs that are + * method. These are the same instances as those passed into the jobs that are * currently executing within the scheduler. The exception to this is when your * application is using Quartz remotely (i.e. via RMI) - in which case you get * a clone of theJobExecutionContext
s, and their references to @@ -58,145 +50,66 @@ * to the job instance that is running). *- * Create a JobExcecutionContext with the given context data. - *
- */ - public JobExecutionContext(Scheduler scheduler, - TriggerFiredBundle firedBundle, Job job) { - this.scheduler = scheduler; - this.trigger = firedBundle.getTrigger(); - this.calendar = firedBundle.getCalendar(); - this.jobDetail = firedBundle.getJobDetail(); - this.job = job; - this.recovering = firedBundle.isRecovering(); - this.fireTime = firedBundle.getFireTime(); - this.scheduledFireTime = firedBundle.getScheduledFireTime(); - this.prevFireTime = firedBundle.getPrevFireTime(); - this.nextFireTime = firedBundle.getNextFireTime(); - - this.jobDataMap = new JobDataMap(); - this.jobDataMap.putAll(jobDetail.getJobDataMap()); - this.jobDataMap.putAll(trigger.getJobDataMap()); - - this.jobDataMap.setMutable(false); - this.trigger.getJobDataMap().setMutable(false); - } - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Interface. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - - /** - ** Get a handle to the
*/ - public Scheduler getScheduler() { - return scheduler; - } + public Scheduler getScheduler(); /** *Scheduler
instance that fired the *Job
. ** Get a handle to the
*/ - public Trigger getTrigger() { - return trigger; - } + public Trigger getTrigger(); /** *Trigger
instance that fired the *Job
. ** Get a handle to the
*/ - public Calendar getCalendar() { - return calendar; - } + public Calendar getCalendar(); /** *Calendar
referenced by theTrigger
* instance that fired theJob
. ** If the
*/ - public boolean isRecovering() { - return recovering; - } + public boolean isRecovering(); - public void incrementRefireCount() { - numRefires++; - } + /** + * Return the {@code TriggerKey} of the originally scheduled and now recovering job. + *Job
is being re-executed because of a 'recovery' * situation, this method will returntrue
. *+ * When recovering a previously failed job execution this method returns the identity + * of the originally firing trigger. This recovering job will have been scheduled for + * the same firing time as the original job, and so is available via the + * {@link #getScheduledFireTime()} method. The original firing time of the job can be + * accessed via the {@link Scheduler#FAILED_JOB_ORIGINAL_TRIGGER_FIRETIME_IN_MILLISECONDS} + * element of this job's {@code JobDataMap}. + * + * @return the recovering trigger details + * @throws IllegalStateException if this is not a recovering job. + */ + public TriggerKey getRecoveringTriggerKey() throws IllegalStateException; - public int getRefireCount() { - return numRefires; - } + public int getRefireCount(); /** *
@@ -209,12 +122,12 @@ *
* - *JobDetail
and the one found on theTrigger
, with * the value in the latter overriding any same-named values in the former. * It is thus considered a 'best practice' that the execute code of a Job - * retrieve data from the JobDataMap found on this object + * retrieve data from the JobDataMap found on this object. *NOTE: Do not - * expect value 'set' into this JobDataMap to somehow be set back onto a - *
StatefulJob
's own JobDataMap. + *NOTE: Do not expect value 'set' into this JobDataMap to somehow be set + * or persisted back onto a job's own JobDataMap - even if it has the + *
* *@PersistJobDataAfterExecution
annotation. *@@ -223,18 +136,14 @@ *
* */ - public JobDataMap getMergedJobDataMap() { - return jobDataMap; - } + public JobDataMap getMergedJobDataMap(); /** ** Get the
*/ - public JobDetail getJobDetail() { - return jobDetail; - } + public JobDetail getJobDetail(); /** *JobDetail
associated with theJob
. *@@ -247,9 +156,7 @@ * interfaces. *
*/ - public Job getJobInstance() { - return job; - } + public Job getJobInstance(); /** * The actual time the trigger fired. For instance the scheduled time may @@ -259,9 +166,7 @@ * @return Returns the fireTime. * @see #getScheduledFireTime() */ - public Date getFireTime() { - return fireTime; - } + public Date getFireTime(); /** * The scheduled time the trigger fired for. For instance the scheduled @@ -271,29 +176,23 @@ * @return Returns the scheduledFireTime. * @see #getFireTime() */ - public Date getScheduledFireTime() { - return scheduledFireTime; - } + public Date getScheduledFireTime(); - public Date getPreviousFireTime() { - return prevFireTime; - } + public Date getPreviousFireTime(); - public Date getNextFireTime() { - return nextFireTime; - } + public Date getNextFireTime(); - public String toString() { - return "JobExecutionContext:" + " trigger: '" - + getTrigger().getFullName() + " job: " - + getJobDetail().getFullName() + " fireTime: '" + getFireTime() - + " scheduledFireTime: " + getScheduledFireTime() - + " previousFireTime: '" + getPreviousFireTime() - + " nextFireTime: " + getNextFireTime() + " isRecovering: " - + isRecovering() + " refireCount: " + getRefireCount(); - } - /** + * Get the unique Id that identifies this particular firing instance of the + * trigger that triggered this job execution. It is unique to this + * JobExecutionContext instance as well. + * + * @return the unique fire instance id + * @see Scheduler#interrupt(String) + */ + public String getFireInstanceId(); + + /** * Returns the result (if any) that theJob
set before its * execution completed (the type of object set as the result is entirely up * to the particular job). @@ -307,10 +206,8 @@ * * @return Returns the result. */ - public Object getResult() { - return result; - } - + public Object getResult(); + /** * Set the result (if any) of theJob
's execution (the type of * object set as the result is entirely up to the particular job). @@ -321,13 +218,9 @@ *{@link TriggerListener}s
that are watching the job's * execution. * - * - * @return Returns the result. */ - public void setResult(Object result) { - this.result = result; - } - + public void setResult(Object result); + /** * The amount of time the job ran for (in milliseconds). The returned * value will be -1 until the job has actually completed (or thrown an @@ -336,16 +229,7 @@ * * @return Returns the jobRunTime. */ - public long getJobRunTime() { - return jobRunTime; - } - - /** - * @param jobRunTime The jobRunTime to set. - */ - public void setJobRunTime(long jobRunTime) { - this.jobRunTime = jobRunTime; - } + public long getJobRunTime(); /** * Put the specified value into the context's data map with the given key. @@ -355,19 +239,16 @@ * completes, and all TriggerListeners and JobListeners have been * notified. * - * @param key - * @param value + * @param key the key for the associated value + * @param value the value to store */ - public void put(Object key, Object value) { - data.put(key, value); - } - + public void put(Object key, Object value); + /** * Get the value with the given key from the context's data map. * - * @param key + * @param key the key for the desired value */ - public Object get(Object key) { - return data.get(key); - } -} + public Object get(Object key); + +} \ No newline at end of file Index: 3rdParty_sources/quartz/org/quartz/JobExecutionException.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/JobExecutionException.java (.../JobExecutionException.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/JobExecutionException.java (.../JobExecutionException.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,19 +16,14 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; /** - ** An exception that can be thrown by a
* *{@link org.quartz.Job}
* to indicate to the Quartz{@link Scheduler}
that an error - * occured while executing, and whether or not theJob
requests + * occurred while executing, and whether or not theJob
requests * to be re-fired immediately (using the same{@link JobExecutionContext}
, * or whether it wants to be unscheduled. - ** Note that if the flag for 'refire immediately' is set, the flags for @@ -43,6 +38,8 @@ */ public class JobExecutionException extends SchedulerException { + private static final long serialVersionUID = 1326342535829043325L; + /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -79,7 +76,7 @@ * Create a JobExcecutionException, with the given cause. *
*/ - public JobExecutionException(Exception cause) { + public JobExecutionException(Throwable cause) { super(cause); } @@ -108,7 +105,7 @@ * the 're-fire immediately' flag set to the given value. * */ - public JobExecutionException(Exception cause, boolean refireImmediately) { + public JobExecutionException(Throwable cause, boolean refireImmediately) { super(cause); refire = refireImmediately; @@ -117,16 +114,36 @@ /** ** Create a JobExcecutionException with the given message, and underlying + * exception. + *
+ */ + public JobExecutionException(String msg, Throwable cause) { + super(msg, cause); + } + + /** + *+ * Create a JobExcecutionException with the given message, and underlying * exception, and the 're-fire immediately' flag set to the given value. *
*/ - public JobExecutionException(String msg, Exception cause, + public JobExecutionException(String msg, Throwable cause, boolean refireImmediately) { super(msg, cause); refire = refireImmediately; } + + /** + * Create a JobExcecutionException with the given message and the 're-fire + * immediately' flag set to the given value. + */ + public JobExecutionException(String msg, boolean refireImmediately) { + super(msg); + refire = refireImmediately; + } + /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -135,6 +152,10 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + public void setRefireImmediately(boolean refire) { + this.refire = refire; + } + public boolean refireImmediately() { return refire; } Index: 3rdParty_sources/quartz/org/quartz/JobKey.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/JobKey.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/JobKey.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,77 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import org.quartz.utils.Key; + +/** + * Uniquely identifies a {@link JobDetail}. + * + *Keys are composed of both a name and group, and the name must be unique + * within the group. If only a group is specified then the default group + * name will be used.
+ * + *Quartz provides a builder-style API for constructing scheduling-related + * entities via a Domain-Specific Language (DSL). The DSL can best be + * utilized through the usage of static imports of the methods on the classes + *
+ * + *TriggerBuilder
,JobBuilder
, + *DateBuilder
,JobKey
,TriggerKey
+ * and the variousScheduleBuilder
implementations.Client code can then use the DSL to write code such as this:
+ *+ * JobDetail job = newJob(MyJob.class) + * .withIdentity("myJob") + * .build(); + * + * Trigger trigger = newTrigger() + * .withIdentity(triggerKey("myTrigger", "myTriggerGroup")) + * .withSchedule(simpleSchedule() + * .withIntervalInHours(1) + * .repeatForever()) + * .startAt(futureDate(10, MINUTES)) + * .build(); + * + * scheduler.scheduleJob(job, trigger); + *+ * + * + * @see Job + * @see Key#DEFAULT_GROUP + */ +public final class JobKey extends Key{ + + private static final long serialVersionUID = -6073883950062574010L; + + public JobKey(String name) { + super(name, null); + } + + public JobKey(String name, String group) { + super(name, group); + } + + public static JobKey jobKey(String name) { + return new JobKey(name, null); + } + + public static JobKey jobKey(String name, String group) { + return new JobKey(name, group); + } + +} Index: 3rdParty_sources/quartz/org/quartz/JobListener.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/JobListener.java (.../JobListener.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/JobListener.java (.../JobListener.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,20 +16,16 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; /** - * * The interface to be implemented by classes that want to be informed when a *
* - * @see Scheduler + * @see ListenerManager#addJobListener(JobListener, Matcher) + * @see Matcher * @see Job * @see JobExecutionContext * @see JobExecutionException @@ -52,13 +48,13 @@ * Get the name of the{@link org.quartz.JobDetail}
executes. In general, * applications that use aScheduler
will not have use for this * mechanism. - *JobListener
. * */ - public String getName(); + String getName(); /** ** Called by the
* *{@link Scheduler}
when a{@link org.quartz.JobDetail}
* is about to be executed (an associated{@link Trigger}
- * has occured). + * has occurred). *@@ -68,19 +64,19 @@ * * @see #jobExecutionVetoed(JobExecutionContext) */ - public void jobToBeExecuted(JobExecutionContext context); + void jobToBeExecuted(JobExecutionContext context); /** *
* Called by the
* * @see #jobToBeExecuted(JobExecutionContext) */ - public void jobExecutionVetoed(JobExecutionContext context); + void jobExecutionVetoed(JobExecutionContext context); /** @@ -90,7 +86,7 @@ *{@link Scheduler}
when a{@link org.quartz.JobDetail}
* was about to be executed (an associated{@link Trigger}
- * has occured), but a{@link TriggerListener}
vetoed it's + * has occurred), but a{@link TriggerListener}
vetoed it's * execution. *triggered(xx)
method has been called. * */ - public void jobWasExecuted(JobExecutionContext context, + void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException); } Index: 3rdParty_sources/quartz/org/quartz/JobPersistenceException.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/JobPersistenceException.java (.../JobPersistenceException.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/JobPersistenceException.java (.../JobPersistenceException.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,20 +16,17 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; /** - ** An exception that is thrown to indicate that there has been a failure in the * scheduler's underlying persistence mechanism. - *
* * @author James House */ public class JobPersistenceException extends SchedulerException { + + private static final long serialVersionUID = -8924958757341995694L; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -46,38 +43,17 @@ */ public JobPersistenceException(String msg) { super(msg); - setErrorCode(ERR_PERSISTENCE); } - /** - *- * Create a
- */ - public JobPersistenceException(String msg, int errCode) { - super(msg, errCode); - } /** *JobPersistenceException
with the given message - * and error code. - ** Create a
*/ - public JobPersistenceException(String msg, Exception cause) { + public JobPersistenceException(String msg, Throwable cause) { super(msg, cause); - setErrorCode(ERR_PERSISTENCE); } - /** - *JobPersistenceException
with the given message * and cause. *- * Create a
- */ - public JobPersistenceException(String msg, Exception cause, int errorCode) { - super(msg, cause, errorCode); - } - } Index: 3rdParty_sources/quartz/org/quartz/ListenerManager.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/ListenerManager.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/ListenerManager.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,277 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import java.util.List; + +/** + * Client programs may be interested in the 'listener' interfaces that are + * available from Quartz. TheJobPersistenceException
with the given message, - * cause and error code. - *{@link JobListener}
interface + * provides notifications ofJob
executions. The + *{@link TriggerListener}
interface provides notifications of + *Trigger
firings. The{@link SchedulerListener}
+ * interface provides notifications ofScheduler
events and + * errors. Listeners can be associated with local schedulers through the + * {@link ListenerManager} interface. + * + *Listener registration order is preserved, and hence notification of listeners + * will be in the order in which they were registered.
+ * + * @author jhouse + * @since 2.0 - previously listeners were managed directly on the Scheduler interface. + */ +public interface ListenerManager { + + /** + * Add the given{@link JobListener}
to theScheduler
, + * and register it to receive events for all Jobs. + * + * Because no matchers are provided, theEverythingMatcher
will be used. + * + * @see Matcher + * @see org.quartz.impl.matchers.EverythingMatcher + */ + public void addJobListener(JobListener jobListener); + + /** + * Add the given{@link JobListener}
to theScheduler
, + * and register it to receive events for Jobs that are matched by the + * given Matcher. + * + * If no matchers are provided, theEverythingMatcher
will be used. + * + * @see Matcher + * @see org.quartz.impl.matchers.EverythingMatcher + */ + public void addJobListener(JobListener jobListener, Matchermatcher); + + /** + * Add the given {@link JobListener}
to theScheduler
, + * and register it to receive events for Jobs that are matched by ANY of the + * given Matchers. + * + * If no matchers are provided, theEverythingMatcher
will be used. + * + * @see Matcher + * @see org.quartz.impl.matchers.EverythingMatcher + */ + public void addJobListener(JobListener jobListener, Matcher... matchers); + + /** + * Add the given {@link JobListener}
to theScheduler
, + * and register it to receive events for Jobs that are matched by ANY of the + * given Matchers. + * + * If no matchers are provided, theEverythingMatcher
will be used. + * + * @see Matcher + * @see org.quartz.impl.matchers.EverythingMatcher + */ + public void addJobListener(JobListener jobListener, List> matchers); + + /** + * Add the given Matcher to the set of matchers for which the listener + * will receive events if ANY of the matchers match. + * + * @param listenerName the name of the listener to add the matcher to + * @param matcher the additional matcher to apply for selecting events + * @return true if the identified listener was found and updated + */ + public boolean addJobListenerMatcher(String listenerName, Matcher matcher); + + /** + * Remove the given Matcher to the set of matchers for which the listener + * will receive events if ANY of the matchers match. + * + * @param listenerName the name of the listener to add the matcher to + * @param matcher the additional matcher to apply for selecting events + * @return true if the given matcher was found and removed from the listener's list of matchers + */ + public boolean removeJobListenerMatcher(String listenerName, Matcher matcher); + + /** + * Set the set of Matchers for which the listener + * will receive events if ANY of the matchers match. + * + * Removes any existing matchers for the identified listener!
+ * + * @param listenerName the name of the listener to add the matcher to + * @param matchers the matchers to apply for selecting events + * @return true if the given matcher was found and removed from the listener's list of matchers + */ + public boolean setJobListenerMatchers(String listenerName, List> matchers); + + /** + * Get the set of Matchers for which the listener + * will receive events if ANY of the matchers match. + * + * + * @param listenerName the name of the listener to add the matcher to + * @return the matchers registered for selecting events for the identified listener + */ + public List > getJobListenerMatchers(String listenerName); + + /** + * Remove the identified {@link JobListener}
from theScheduler
. + * + * @return true if the identified listener was found in the list, and + * removed. + */ + public boolean removeJobListener(String name); + + /** + * Get a List containing all of the{@link JobListener}
s in + * theScheduler
, in the order in which they were registered. + */ + public ListgetJobListeners(); + + /** + * Get the {@link JobListener}
that has the given name. + */ + public JobListener getJobListener(String name); + + /** + * Add the given{@link TriggerListener}
to theScheduler
, + * and register it to receive events for all Triggers. + * + * Because no matcher is provided, theEverythingMatcher
will be used. + * + * @see Matcher + * @see org.quartz.impl.matchers.EverythingMatcher + */ + public void addTriggerListener(TriggerListener triggerListener); + + /** + * Add the given{@link TriggerListener}
to theScheduler
, + * and register it to receive events for Triggers that are matched by the + * given Matcher. + * + * If no matcher is provided, theEverythingMatcher
will be used. + * + * @see Matcher + * @see org.quartz.impl.matchers.EverythingMatcher + */ + public void addTriggerListener(TriggerListener triggerListener, Matchermatcher); + + /** + * Add the given {@link TriggerListener}
to theScheduler
, + * and register it to receive events for Triggers that are matched by ANY of the + * given Matchers. + * + * If no matcher is provided, theEverythingMatcher
will be used. + * + * @see Matcher + * @see org.quartz.impl.matchers.EverythingMatcher + */ + public void addTriggerListener(TriggerListener triggerListener, Matcher... matchers); + + /** + * Add the given {@link TriggerListener}
to theScheduler
, + * and register it to receive events for Triggers that are matched by ANY of the + * given Matchers. + * + * If no matcher is provided, theEverythingMatcher
will be used. + * + * @see Matcher + * @see org.quartz.impl.matchers.EverythingMatcher + */ + public void addTriggerListener(TriggerListener triggerListener, List> matchers); + + /** + * Add the given Matcher to the set of matchers for which the listener + * will receive events if ANY of the matchers match. + * + * @param listenerName the name of the listener to add the matcher to + * @param matcher the additional matcher to apply for selecting events + * @return true if the identified listener was found and updated + */ + public boolean addTriggerListenerMatcher(String listenerName, Matcher matcher); + + /** + * Remove the given Matcher to the set of matchers for which the listener + * will receive events if ANY of the matchers match. + * + * @param listenerName the name of the listener to add the matcher to + * @param matcher the additional matcher to apply for selecting events + * @return true if the given matcher was found and removed from the listener's list of matchers + */ + public boolean removeTriggerListenerMatcher(String listenerName, Matcher matcher); + + /** + * Set the set of Matchers for which the listener + * will receive events if ANY of the matchers match. + * + * Removes any existing matchers for the identified listener!
+ * + * @param listenerName the name of the listener to add the matcher to + * @param matchers the matchers to apply for selecting events + * @return true if the given matcher was found and removed from the listener's list of matchers + */ + public boolean setTriggerListenerMatchers(String listenerName, List> matchers); + + /** + * Get the set of Matchers for which the listener + * will receive events if ANY of the matchers match. + * + * + * @param listenerName the name of the listener to add the matcher to + * @return the matchers registered for selecting events for the identified listener + */ + public List > getTriggerListenerMatchers( String listenerName); + + /** + * Remove the identified {@link TriggerListener}
from theScheduler
. + * + * @return true if the identified listener was found in the list, and + * removed. + */ + public boolean removeTriggerListener(String name); + + /** + * Get a List containing all of the{@link TriggerListener}
s + * in theScheduler
, in the order in which they were registered. + */ + public ListgetTriggerListeners(); + + /** + * Get the {@link TriggerListener}
that has the given name. + */ + public TriggerListener getTriggerListener(String name); + + /** + * Register the given{@link SchedulerListener}
with the + *Scheduler
. + */ + public void addSchedulerListener(SchedulerListener schedulerListener); + + /** + * Remove the given{@link SchedulerListener}
from the + *Scheduler
. + * + * @return true if the identified listener was found in the list, and + * removed. + */ + public boolean removeSchedulerListener(SchedulerListener schedulerListener); + + /** + * Get a List containing all of the{@link SchedulerListener}
s + * registered with theScheduler
, in the order in which they were registered. + */ + public ListgetSchedulerListeners(); + +} \ No newline at end of file Index: 3rdParty_sources/quartz/org/quartz/Matcher.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/Matcher.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/Matcher.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,38 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import java.io.Serializable; + +import org.quartz.utils.Key; + +/** + * Matchers can be used in various {@link Scheduler} API methods to + * select the entities that should be operated upon. + * + * @author jhouse + * @since 2.0 + */ +public interface Matcher > extends Serializable { + + boolean isMatch(T key); + + public int hashCode(); + + public boolean equals(Object obj); +} Fisheye: Tag c208628989d52041b3765784f4c8cbfd6c80d47b refers to a dead (removed) revision in file `3rdParty_sources/quartz/org/quartz/NthIncludedDayTrigger.java'. Fisheye: No comparison available. Pass `N' to diff? Index: 3rdParty_sources/quartz/org/quartz/ObjectAlreadyExistsException.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/ObjectAlreadyExistsException.java (.../ObjectAlreadyExistsException.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/ObjectAlreadyExistsException.java (.../ObjectAlreadyExistsException.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,22 +16,19 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; /** - * * An exception that is thrown to indicate that an attempt to store a new * object (i.e.
* * @author James House */ public class ObjectAlreadyExistsException extends JobPersistenceException { + + private static final long serialVersionUID = -558301282071659896L; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -63,8 +60,7 @@ * */ public ObjectAlreadyExistsException(JobDetail offendingJob) { - super("Unable to store Job with name: '" + offendingJob.getName() - + "' and group: '" + offendingJob.getGroup() + super("Unable to store Job : '" + offendingJob.getKey() + "', because one already exists with this identification."); } @@ -81,8 +77,8 @@ */ public ObjectAlreadyExistsException(Trigger offendingTrigger) { super("Unable to store Trigger with name: '" - + offendingTrigger.getName() + "' and group: '" - + offendingTrigger.getGroup() + + offendingTrigger.getKey().getName() + "' and group: '" + + offendingTrigger.getKey().getGroup() + "', because one already exists with this identification."); } Index: 3rdParty_sources/quartz/org/quartz/PersistJobDataAfterExecution.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/PersistJobDataAfterExecution.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/PersistJobDataAfterExecution.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,44 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An annotation that marks a {@link Job} class as one that makes updates to its + * {@link JobDataMap} during execution, and wishes the scheduler to re-store the + *{@link org.quartz.JobDetail}
,{@link Trigger}
* or{@link Calendar}
) in a{@link Scheduler}
* failed, because one with the same name & group already exists. - *JobDataMap
when execution completes. + * + *Jobs that are marked with this annotation should also seriously consider + * using the {@link DisallowConcurrentExecution} annotation, to avoid data + * storage race conditions with concurrently executing job instances.
+ * + * @see DisallowConcurrentExecution + * + * @author jhouse + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface PersistJobDataAfterExecution { + +} Index: 3rdParty_sources/quartz/org/quartz/ScheduleBuilder.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/ScheduleBuilder.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/ScheduleBuilder.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,26 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import org.quartz.spi.MutableTrigger; + +public abstract class ScheduleBuilder{ + + protected abstract MutableTrigger build(); + +} Index: 3rdParty_sources/quartz/org/quartz/Scheduler.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/Scheduler.java (.../Scheduler.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/Scheduler.java (.../Scheduler.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,26 +16,25 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Set; +import org.quartz.Trigger.TriggerState; +import org.quartz.impl.matchers.GroupMatcher; import org.quartz.spi.JobFactory; +import org.quartz.utils.Key; /** - * * This is the main interface of a Quartz Scheduler. - *
* *- * A
* @@ -87,7 +86,8 @@ * provides notifications ofScheduler
maintains a registery of{@link org.quartz.JobDetail}
- * s and{@link Trigger}
s. Once registered, theScheduler
- * is responible for executingJob
s when their associated + * AScheduler
maintains a registry of{@link org.quartz.JobDetail}
s + * and{@link Trigger}
s. Once registered, theScheduler
+ * is responsible for executingJob
s when their associated *Trigger
s fire (when their scheduled time arrives). *Job
executions. The{@link TriggerListener}
* interface provides notifications ofTrigger
firings. The *{@link SchedulerListener}
interface provides notifications of - *Scheduler
events and errors. + *Scheduler
events and errors. Listeners can be associated with + * local schedulers through the {@link ListenerManager} interface. * * *@@ -97,7 +97,9 @@ * * @see Job * @see JobDetail + * @see JobBuilder * @see Trigger + * @see TriggerBuilder * @see JobListener * @see TriggerListener * @see SchedulerListener @@ -116,40 +118,78 @@ */ /** - *
- * A (possibly) usefull constant that can be used for specifying the group + * A (possibly) useful constant that can be used for specifying the group * that
*/ - public static final String DEFAULT_GROUP = "DEFAULT"; + String DEFAULT_GROUP = Key.DEFAULT_GROUP; /** - *Job
andTrigger
instances belong to. - ** A constant
+ * ("RECOVERING_JOBS") for the name of aTrigger
group name used internally by the * scheduler - clients should not use the value of this constant - * ("MANUAL_TRIGGER") for thename of aTrigger
's group. - *Trigger
's group. + * + * @see org.quartz.JobDetail#requestsRecovery() */ - public static final String DEFAULT_MANUAL_TRIGGERS = "MANUAL_TRIGGER"; + String DEFAULT_RECOVERY_GROUP = "RECOVERING_JOBS"; /** - ** A constant
+ * ("FAILED_OVER_JOBS") for the name of aTrigger
group name used internally by the * scheduler - clients should not use the value of this constant - * ("RECOVERING_JOBS") for thename of aTrigger
's group. - *Trigger
's group. + * + * @see org.quartz.JobDetail#requestsRecovery() */ - public static final String DEFAULT_RECOVERY_GROUP = "RECOVERING_JOBS"; + String DEFAULT_FAIL_OVER_GROUP = "FAILED_OVER_JOBS"; + /** - *- * A constant
+ * A constantTrigger
group name used internally by the - * scheduler - clients should not use the value of this constant - * ("FAILED_OVER_JOBS") for thename of aTrigger
's group. - *JobDataMap
key that can be used to retrieve the + * name of the originalTrigger
from a recovery trigger's + * data map in the case of a job recovering after a failed scheduler + * instance. + * + * @see org.quartz.JobDetail#requestsRecovery() */ - public static final String DEFAULT_FAIL_OVER_GROUP = "FAILED_OVER_JOBS"; + String FAILED_JOB_ORIGINAL_TRIGGER_NAME = "QRTZ_FAILED_JOB_ORIG_TRIGGER_NAME"; + /** + * A constantJobDataMap
key that can be used to retrieve the + * group of the originalTrigger
from a recovery trigger's + * data map in the case of a job recovering after a failed scheduler + * instance. + * + * @see org.quartz.JobDetail#requestsRecovery() + */ + String FAILED_JOB_ORIGINAL_TRIGGER_GROUP = "QRTZ_FAILED_JOB_ORIG_TRIGGER_GROUP"; + + /** + * A constantJobDataMap
key that can be used to retrieve the + * fire time of the originalTrigger
from a recovery + * trigger's data map in the case of a job recovering after a failed scheduler + * instance. + * + *Note that this is the time the original firing actually occurred, + * which may be different from the scheduled fire time - as a trigger doesn't + * always fire exactly on time.
+ * + * @see org.quartz.JobDetail#requestsRecovery() + */ + String FAILED_JOB_ORIGINAL_TRIGGER_FIRETIME_IN_MILLISECONDS = "QRTZ_FAILED_JOB_ORIG_TRIGGER_FIRETIME_IN_MILLISECONDS_AS_STRING"; + + /** + * A constantJobDataMap
key that can be used to retrieve the + * scheduled fire time of the originalTrigger
from a recovery + * trigger's data map in the case of a job recovering after a failed scheduler + * instance. + * + *Note that this is the time the original firing was scheduled for, + * which may be different from the actual firing time - as a trigger doesn't + * always fire exactly on time.
+ * + * @see org.quartz.JobDetail#requestsRecovery() + */ + String FAILED_JOB_ORIGINAL_TRIGGER_SCHEDULED_FIRETIME_IN_MILLISECONDS = "QRTZ_FAILED_JOB_ORIG_TRIGGER_SCHEDULED_FIRETIME_IN_MILLISECONDS_AS_STRING"; + /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -159,39 +199,31 @@ */ /** - ** Returns the name of the
*/ - public String getSchedulerName() throws SchedulerException; + String getSchedulerName() throws SchedulerException; /** - *Scheduler
. - ** Returns the instance Id of the
*/ - public String getSchedulerInstanceId() throws SchedulerException; + String getSchedulerInstanceId() throws SchedulerException; /** - *Scheduler
. - ** Returns the
*/ - public SchedulerContext getContext() throws SchedulerException; + SchedulerContext getContext() throws SchedulerException; /////////////////////////////////////////////////////////////////////////// /// - /// Schedululer State Management Methods + /// Scheduler State Management Methods /// /////////////////////////////////////////////////////////////////////////// - + /** - *SchedulerContext
of theScheduler
. - ** Starts the
* *Scheduler
's threads that fire{@link Trigger}s
. * When a scheduler is first created it is in "stand-by" mode, and will not * fire triggers. The scheduler can also be put into stand-by mode by * calling thestandby()
method. - ** The misfire/recovery process will be started, if it is the initial call @@ -201,17 +233,48 @@ * @throws SchedulerException * if
shutdown()
has been called, or there is an * error within theScheduler
. - * - * @see #standby - * @see #shutdown + * + * @see #startDelayed(int) + * @see #standby() + * @see #shutdown() */ - public void start() throws SchedulerException; + void start() throws SchedulerException; /** + * Calls {#start()} after the indicated number of seconds. + * (This call does not block). This can be useful within applications that + * have initializers that create the scheduler immediately, before the + * resources needed by the executing jobs have been fully initialized. + * + * @throws SchedulerException + * ifshutdown()
has been called, or there is an + * error within theScheduler
. + * + * @see #start() + * @see #standby() + * @see #shutdown() + */ + void startDelayed(int seconds) throws SchedulerException; + + /** + * Whether the scheduler has been started. + * *- * Temporarily halts the
* + * @see #start() + * @see #isShutdown() + * @see #isInStandbyMode() + */ + boolean isStarted() throws SchedulerException; + + /** + * Temporarily halts theScheduler
's firing of{@link Trigger}s
. + * Note: This only reflects whether{@link #start()}
has ever + * been called on this Scheduler, so it will returntrue
even + * if theScheduler
is currently in standby mode or has been + * since shutdown. *Scheduler
's firing of{@link Trigger}s
. + * ** When
start()
is called (to bring the scheduler out of * stand-by mode), trigger misfire instructions will NOT be applied @@ -227,50 +290,32 @@ * @see #start() * @see #pauseAll() */ - public void standby() throws SchedulerException; + void standby() throws SchedulerException; /** - * @deprecated replaced by better-named standby() method. - * @see #standby() - */ - public void pause() throws SchedulerException; - - /** - ** Reports whether the
* * @see #standby() * @see #start() */ - public boolean isInStandbyMode() throws SchedulerException; + boolean isInStandbyMode() throws SchedulerException; /** - * @deprecated - * @see #isInStandbyMode() - */ - public boolean isPaused() throws SchedulerException; - - /** - *Scheduler
is in stand-by mode. - ** Halts the
* *Scheduler
's firing of{@link Trigger}s
, * and cleans up all resources associated with the Scheduler. Equivalent to *shutdown(false)
. - ** The scheduler cannot be re-started. *
* * @see #shutdown(boolean) */ - public void shutdown() throws SchedulerException; + void shutdown() throws SchedulerException; /** - ** Halts the
* *Scheduler
's firing of{@link Trigger}s
, * and cleans up all resources associated with the Scheduler. - ** The scheduler cannot be re-started. @@ -282,33 +327,33 @@ * * @see #shutdown */ - public void shutdown(boolean waitForJobsToComplete) - throws SchedulerException; + void shutdown(boolean waitForJobsToComplete) + throws SchedulerException; /** - *
* Reports whether the
*/ - public boolean isShutdown() throws SchedulerException; + boolean isShutdown() throws SchedulerException; /** - *Scheduler
has been shutdown. - *- * Get a
* *SchedulerMetaData
object describiing the settings + * Get aSchedulerMetaData
object describing the settings * and capabilities of the scheduler instance. - ** Note that the data returned is an 'instantaneous' snap-shot, and that as * soon as it's returned, the meta data values may be different. *
*/ - public SchedulerMetaData getMetaData() throws SchedulerException; + SchedulerMetaData getMetaData() throws SchedulerException; /** - ** Return a list of
JobExecutionContext
objects that - * represent all currently executing Jobs. + * represent all currently executing Jobs in this Scheduler instance. + * + *+ * This method is not cluster aware. That is, it will only return Jobs + * currently executing in this Scheduler instance, not across the entire + * cluster. *
* *@@ -320,37 +365,46 @@ * * @see JobExecutionContext */ - public List getCurrentlyExecutingJobs() throws SchedulerException; + List
+ * + *getCurrentlyExecutingJobs() throws SchedulerException; /** - * * Set the
* *JobFactory
that will be responsible for producing * instances ofJob
classes. - ** JobFactories may be of use to those wishing to have their application * produce
* - * @see org.quart.spi.JobFactory - * @throws SchedulerException + * @see org.quartz.spi.JobFactory */ - public void setJobFactory(JobFactory factory) throws SchedulerException; + void setJobFactory(JobFactory factory) throws SchedulerException; + + /** + * Get a reference to the scheduler'sJob
instances via some special mechanism, such as to - * give the opertunity for dependency injection. + * give the opportunity for dependency injection. *ListenerManager
, + * through which listeners may be registered. + * + * @return the scheduler'sListenerManager
+ * @throws SchedulerException if the scheduler is not local + * @see ListenerManager + * @see JobListener + * @see TriggerListener + * @see SchedulerListener + */ + ListenerManager getListenerManager() throws SchedulerException; + /////////////////////////////////////////////////////////////////////////// /// /// Scheduling-related Methods /// /////////////////////////////////////////////////////////////////////////// /** - ** Add the given
* *{@link org.quartz.JobDetail}
to the * Scheduler, and associate the given{@link Trigger}
with * it. - ** If the given Trigger does not reference any
Job
, then it @@ -361,272 +415,327 @@ * if the Job or Trigger cannot be added to the Scheduler, or * there is an internal Scheduler error. */ - public Date scheduleJob(JobDetail jobDetail, Trigger trigger) - throws SchedulerException; + Date scheduleJob(JobDetail jobDetail, Trigger trigger) + throws SchedulerException; /** - ** Schedule the given
* * @throws SchedulerException * if the indicated Job does not exist, or the Trigger cannot be * added to the Scheduler, or there is an internal Scheduler * error. */ - public Date scheduleJob(Trigger trigger) throws SchedulerException; + Date scheduleJob(Trigger trigger) throws SchedulerException; /** - *{@link org.quartz.Trigger}
with the *Job
identified by theTrigger
's settings. - *+ * Schedule all of the given jobs with the related set of triggers. + * + *
If any of the given jobs or triggers already exist (or more + * specifically, if the keys are not unique) and the replace + * parameter is not set to true then an exception will be thrown.
+ * + * @throws ObjectAlreadyExistsException if the job/trigger keys + * are not unique and the replace flag is not set to true. + */ + void scheduleJobs(Map> triggersAndJobs, boolean replace) throws SchedulerException; + + /** + * Schedule the given job with the related set of triggers. + * + * If any of the given job or triggers already exist (or more + * specifically, if the keys are not unique) and the replace + * parameter is not set to true then an exception will be thrown.
+ * + * @throws ObjectAlreadyExistsException if the job/trigger keys + * are not unique and the replace flag is not set to true. + */ + void scheduleJob(JobDetail jobDetail, Set extends Trigger> triggersForJob, boolean replace) throws SchedulerException; + + /** * Remove the indicated{@link Trigger}
from the scheduler. - *If the related job does not have any other triggers, and the job is + * not durable, then the job will also be deleted.
*/ - public boolean unscheduleJob(String triggerName, String groupName) - throws SchedulerException; + boolean unscheduleJob(TriggerKey triggerKey) + throws SchedulerException; /** - *+ * Remove all of the indicated
{@link Trigger}
s from the scheduler. + * + *If the related job does not have any other triggers, and the job is + * not durable, then the job will also be deleted.
+ * + *Note that while this bulk operation is likely more efficient than + * invoking
+ */ + boolean unscheduleJobs(ListunscheduleJob(TriggerKey triggerKey)
several + * times, it may have the adverse affect of holding data locks for a + * single long duration of time (rather than lots of small durations + * of time).triggerKeys) + throws SchedulerException; + + /** * Remove (delete) the {@link org.quartz.Trigger}
with the - * given name, and store the new given one - which must be associated + * given key, and store the new given one - which must be associated * with the same job (the new trigger must have the job name & group specified) * - however, the new trigger need not have the same name as the old trigger. - * * - * @param triggerName - * The name of theTrigger
to be replaced. - * @param groupName - * The group name of theTrigger
to be replaced. + * @param triggerKey identity of the trigger to replace * @param newTrigger * The newTrigger
to be stored. + * * @returnnull
if aTrigger
with the given - * name & group was not found and removed from the store, otherwise - * the first fire time of the newly scheduled trigger. + * name & group was not found and removed from the store (and the + * new trigger is therefore not stored), otherwise + * the first fire time of the newly scheduled trigger is returned. */ - public Date rescheduleJob(String triggerName, - String groupName, Trigger newTrigger) throws SchedulerException; - + Date rescheduleJob(TriggerKey triggerKey, Trigger newTrigger) + throws SchedulerException; /** - ** Add the given
* *Job
to the Scheduler - with no associated *Trigger
. TheJob
will be 'dormant' until * it is scheduled with aTrigger
, orScheduler.triggerJob()
* is called for it. - ** The
- * + * + * @see #addJob(JobDetail, boolean, boolean) + * * @throws SchedulerException * if there is an internal Scheduler error, or if the Job is not * durable, or a Job with the same name already exists, and *Job
must by definition be 'durable', if it is not, * SchedulerException will be thrown. *replace
isfalse
. */ - public void addJob(JobDetail jobDetail, boolean replace) - throws SchedulerException; + void addJob(JobDetail jobDetail, boolean replace) + throws SchedulerException; /** + * Add the givenJob
to the Scheduler - with no associated + *Trigger
. TheJob
will be 'dormant' until + * it is scheduled with aTrigger
, orScheduler.triggerJob()
+ * is called for it. + * *+ * With the
+ * + * @throws SchedulerException + * if there is an internal Scheduler error, or if the Job is not + * durable, or a Job with the same name already exists, and + *storeNonDurableWhileAwaitingScheduling
parameter + * set totrue
, a non-durable job can be stored. Once it is + * scheduled, it will resume normal non-durable behavior (i.e. be deleted + * once there are no remaining associated triggers). + *replace
isfalse
. + */ + void addJob(JobDetail jobDetail, boolean replace, boolean storeNonDurableWhileAwaitingScheduling) + throws SchedulerException; + + /** * Delete the identifiedJob
from the Scheduler - and any * associatedTrigger
s. - * * * @return true if the Job was found and deleted. * @throws SchedulerException * if there is an internal Scheduler error. */ - public boolean deleteJob(String jobName, String groupName) - throws SchedulerException; + boolean deleteJob(JobKey jobKey) + throws SchedulerException; /** - *- * Trigger the identified
+ * Delete the identified{@link org.quartz.JobDetail}
- * (execute it now) - the generated trigger will be non-volatile. - *Job
s from the Scheduler - and any + * associatedTrigger
s. + * + *Note that while this bulk operation is likely more efficient than + * invoking
+ * + * @return true if all of the Jobs were found and deleted, false if + * one or more were not deleted. + * @throws SchedulerException + * if there is an internal Scheduler error. */ - public void triggerJob(String jobName, String groupName) - throws SchedulerException; - + boolean deleteJobs(ListdeleteJob(JobKey jobKey)
several + * times, it may have the adverse affect of holding data locks for a + * single long duration of time (rather than lots of small durations + * of time).jobKeys) + throws SchedulerException; + /** - * * Trigger the identified
+ * (execute it now). */ - public void triggerJobWithVolatileTrigger(String jobName, String groupName) - throws SchedulerException; + void triggerJob(JobKey jobKey) + throws SchedulerException; /** - *{@link org.quartz.JobDetail}
- * (execute it now) - the generated trigger will be volatile. - ** Trigger the identified
+ * (execute it now). * - * @param jobName the name of the Job to trigger - * @param groupName the group name of the Job to trigger * @param data the (possibly{@link org.quartz.JobDetail}
- * (execute it now) - the generated trigger will be non-volatile. - *null
) JobDataMap to be * associated with the trigger that fires the job immediately. */ - public void triggerJob(String jobName, String groupName, JobDataMap data) - throws SchedulerException; + void triggerJob(JobKey jobKey, JobDataMap data) + throws SchedulerException; /** - *- * Trigger the identified
- * - * @param jobName the name of the Job to trigger - * @param groupName the group name of the Job to trigger - * @param data the (possibly{@link org.quartz.JobDetail}
- * (execute it now) - the generated trigger will be volatile. - *null
) JobDataMap to be - * associated with the trigger that fires the job immediately. - */ - public void triggerJobWithVolatileTrigger(String jobName, String groupName, JobDataMap data) - throws SchedulerException; - - /** - ** Pause the
+ * key - by pausing all of its current{@link org.quartz.JobDetail}
with the given - * name - by pausing all of its currentTrigger
s. - *Trigger
s. * - * @see #resumeJob(String, String) + * @see #resumeJob(JobKey) */ - public void pauseJob(String jobName, String groupName) - throws SchedulerException; + void pauseJob(JobKey jobKey) + throws SchedulerException; /** - ** Pause all of the
- * + * matching groups - by pausing all of their{@link org.quartz.JobDetail}s
in the - * given group - by pausing all of theirTrigger
s. - *Trigger
s. + * *- * The Scheduler will "remember" that the group is paused, and impose the - * pause on any new jobs that are added to the group while the group is - * paused. + * The Scheduler will "remember" the groups paused, and impose the + * pause on any new jobs that are added to any of those groups + * until it is resumed. *
* - * @see #resumeJobGroup(String) + *NOTE: There is a limitation that only exactly matched groups + * can be remembered as paused. For example, if there are pre-existing + * job in groups "aaa" and "bbb" and a matcher is given to pause + * groups that start with "a" then the group "aaa" will be remembered + * as paused and any subsequently added jobs in group "aaa" will be paused, + * however if a job is added to group "axx" it will not be paused, + * as "axx" wasn't known at the time the "group starts with a" matcher + * was applied. HOWEVER, if there are pre-existing groups "aaa" and + * "bbb" and a matcher is given to pause the group "axx" (with a + * group equals matcher) then no jobs will be paused, but it will be + * remembered that group "axx" is paused and later when a job is added + * in that group, it will become paused.
+ * + * @param matcher The matcher to evaluate against know groups + * @throws SchedulerException On error + * @see #resumeJobs(org.quartz.impl.matchers.GroupMatcher) */ - public void pauseJobGroup(String groupName) throws SchedulerException; + void pauseJobs(GroupMatchermatcher) throws SchedulerException; /** - * - * Pause the
+ * Pause the{@link Trigger}
with the given name. - *{@link Trigger}
with the given key. * - * @see #resumeTrigger(String, String) + * @see #resumeTrigger(TriggerKey) */ - public void pauseTrigger(String triggerName, String groupName) - throws SchedulerException; + void pauseTrigger(TriggerKey triggerKey) + throws SchedulerException; /** - *- * Pause all of the
+ * Pause all of the{@link Trigger}s
in the given group. - *{@link Trigger}s
in the groups matching. * *- * The Scheduler will "remember" that the group is paused, and impose the - * pause on any new triggers that are added to the group while the group is - * paused. + * The Scheduler will "remember" all the groups paused, and impose the + * pause on any new triggers that are added to any of those groups + * until it is resumed. *
* - * @see #resumeTriggerGroup(String) + *NOTE: There is a limitation that only exactly matched groups + * can be remembered as paused. For example, if there are pre-existing + * triggers in groups "aaa" and "bbb" and a matcher is given to pause + * groups that start with "a" then the group "aaa" will be remembered as + * paused and any subsequently added triggers in that group be paused, + * however if a trigger is added to group "axx" it will not be paused, + * as "axx" wasn't known at the time the "group starts with a" matcher + * was applied. HOWEVER, if there are pre-existing groups "aaa" and + * "bbb" and a matcher is given to pause the group "axx" (with a + * group equals matcher) then no triggers will be paused, but it will be + * remembered that group "axx" is paused and later when a trigger is added + * in that group, it will become paused.
+ * + * @param matcher The matcher to evaluate against know groups + * @throws SchedulerException + * @see #resumeTriggers(org.quartz.impl.matchers.GroupMatcher) */ - public void pauseTriggerGroup(String groupName) throws SchedulerException; + void pauseTriggers(GroupMatchermatcher) throws SchedulerException; /** - * * Resume (un-pause) the
+ * the given key. * *{@link org.quartz.JobDetail}
with - * the given name. - ** If any of the
* - * @see #pauseJob(String, String) + * @see #pauseJob(JobKey) */ - public void resumeJob(String jobName, String groupName) - throws SchedulerException; + void resumeJob(JobKey jobKey) + throws SchedulerException; /** - *Job
'sTrigger
s missed one * or more fire-times, then theTrigger
's misfire * instruction will be applied. ** Resume (un-pause) all of the
+ * in matching groups. * *{@link org.quartz.JobDetail}s
- * in the given group. - ** If any of the
* - * @see #pauseJobGroup(String) + * @param matcher The matcher to evaluate against known paused groups + * @throws SchedulerException On error + * @see #pauseJobs(GroupMatcher) */ - public void resumeJobGroup(String groupName) throws SchedulerException; + void resumeJobs(GroupMatcherJob
s hadTrigger
s that * missed one or more fire-times, then theTrigger
's * misfire instruction will be applied. *matcher) throws SchedulerException; /** - * * Resume (un-pause) the
+ * key. * *{@link Trigger}
with the given - * name. - ** If the
* - * @see #pauseTrigger(String, String) + * @see #pauseTrigger(TriggerKey) */ - public void resumeTrigger(String triggerName, String groupName) - throws SchedulerException; + void resumeTrigger(TriggerKey triggerKey) + throws SchedulerException; /** - *Trigger
missed one or more fire-times, then the *Trigger
's misfire instruction will be applied. *- * Resume (un-pause) all of the
+ * Resume (un-pause) all of the{@link Trigger}s
in the - * given group. - *{@link Trigger}s
in matching groups. * ** If any
* - * @see #pauseTriggerGroup(String) + * @param matcher The matcher to evaluate against know paused groups + * @throws SchedulerException On error + * @see #pauseTriggers(org.quartz.impl.matchers.GroupMatcher) */ - public void resumeTriggerGroup(String groupName) throws SchedulerException; + void resumeTriggers(GroupMatcherTrigger
missed one or more fire-times, then the *Trigger
's misfire instruction will be applied. *matcher) throws SchedulerException; /** - * * Pause all triggers - similar to calling
* *pauseTriggerGroup(group)
* on every group, however, after using this methodresumeAll()
* must be called to clear the scheduler's state of 'remembering' that all * new triggers will be paused as they are added. - ** When
* * @see #resumeAll() - * @see #pauseTriggerGroup(String) + * @see #pauseTriggers(org.quartz.impl.matchers.GroupMatcher) * @see #standby() */ - public void pauseAll() throws SchedulerException; + void pauseAll() throws SchedulerException; /** - *resumeAll()
is called (to un-pause), trigger misfire * instructions WILL be applied. ** Resume (un-pause) all triggers - similar to calling *
* *resumeTriggerGroup(group)
on every group. - ** If any
Trigger
missed one or more fire-times, then the @@ -635,95 +744,89 @@ * * @see #pauseAll() */ - public void resumeAll() throws SchedulerException; + void resumeAll() throws SchedulerException; /** - ** Get the names of all known
*/ - public String[] getJobGroupNames() throws SchedulerException; + List{@link org.quartz.JobDetail}
* groups. - *getJobGroupNames() throws SchedulerException; /** - * - * Get the names of all the
+ * Get the keys of all the{@link org.quartz.JobDetail}s
- * in the given group. - *{@link org.quartz.JobDetail}s
+ * in the matching groups. + * @param matcher Matcher to evaluate against known groups + * @return Set of all keys matching + * @throws SchedulerException On error */ - public String[] getJobNames(String groupName) throws SchedulerException; + SetgetJobKeys(GroupMatcher matcher) throws SchedulerException; /** - * * Get all
{@link Trigger}
s that are associated with the * identified{@link org.quartz.JobDetail}
. + * + *The returned Trigger objects will be snap-shots of the actual stored + * triggers. If you wish to modify a trigger, you must re-store the + * trigger afterward (e.g. see {@link #rescheduleJob(TriggerKey, Trigger)}). *
+ * */ - public Trigger[] getTriggersOfJob(String jobName, String groupName) - throws SchedulerException; + List extends Trigger> getTriggersOfJob(JobKey jobKey) + throws SchedulerException; /** - ** Get the names of all known
*/ - public String[] getTriggerGroupNames() throws SchedulerException; + List{@link Trigger}
groups. - *getTriggerGroupNames() throws SchedulerException; /** - * * Get the names of all the
+ * @param matcher Matcher to evaluate against known groups + * @return List of all keys matching + * @throws SchedulerException On error */ - public String[] getTriggerNames(String groupName) throws SchedulerException; + Set{@link Trigger}s
in the given * group. - *getTriggerKeys(GroupMatcher matcher) throws SchedulerException; /** - * * Get the names of all
- * - * @return - * @throws SchedulerException */ - public Set getPausedTriggerGroups() throws SchedulerException; + Set{@link Trigger}
groups that are paused. - *getPausedTriggerGroups() throws SchedulerException; /** - * * Get the
{@link JobDetail}
for theJob
- * instance with the given name and group. + * instance with the given key. + * + *The returned JobDetail object will be a snap-shot of the actual stored + * JobDetail. If you wish to modify the JobDetail, you must re-store the + * JobDetail afterward (e.g. see {@link #addJob(JobDetail, boolean)}). *
+ * */ - public JobDetail getJobDetail(String jobName, String jobGroup) - throws SchedulerException; + JobDetail getJobDetail(JobKey jobKey) + throws SchedulerException; /** - *- * Get the
{@link Trigger}
instance with the given name and - * group. + * Get the{@link Trigger}
instance with the given key. + * + *The returned Trigger object will be a snap-shot of the actual stored + * trigger. If you wish to modify the trigger, you must re-store the + * trigger afterward (e.g. see {@link #rescheduleJob(TriggerKey, Trigger)}). *
*/ - public Trigger getTrigger(String triggerName, String triggerGroup) - throws SchedulerException; + Trigger getTrigger(TriggerKey triggerKey) + throws SchedulerException; /** - ** Get the current state of the identified
* - * @see Trigger#STATE_NORMAL - * @see Trigger#STATE_PAUSED - * @see Trigger#STATE_COMPLETE - * @see Trigger#STATE_ERROR - * @see Trigger#STATE_BLOCKED - * @see Trigger#STATE_NONE + * @see Trigger.TriggerState */ - public int getTriggerState(String triggerName, String triggerGroup) - throws SchedulerException; + TriggerState getTriggerState(TriggerKey triggerKey) + throws SchedulerException; /** - *{@link Trigger}
. - ** Add (register) the given
* * @param updateTriggers whether or not to update existing triggers that * referenced the already existing calendar so that they are 'correct' @@ -735,40 +838,39 @@ * the same name already exists, andCalendar
to the Scheduler. - *replace
is *false
. */ - public void addCalendar(String calName, Calendar calendar, boolean replace, boolean updateTriggers) - throws SchedulerException; + void addCalendar(String calName, Calendar calendar, boolean replace, boolean updateTriggers) + throws SchedulerException; /** - ** Delete the identified
Calendar
from the Scheduler. + * + *+ * If removal of the
* * @return true if the Calendar was found and deleted. * @throws SchedulerException - * if there is an internal Scheduler error. + * if there is an internal Scheduler error, or one or more + * triggers reference the calendar */ - public boolean deleteCalendar(String calName) throws SchedulerException; + boolean deleteCalendar(String calName) throws SchedulerException; /** - *Calendar
would result in + *Trigger
s pointing to non-existent calendars, then a + *SchedulerException
will be thrown. ** Get the
*/ - public Calendar getCalendar(String calName) throws SchedulerException; + Calendar getCalendar(String calName) throws SchedulerException; /** - *{@link Calendar}
instance with the given name. - ** Get the names of all registered
*/ - public String[] getCalendarNames() throws SchedulerException; + List{@link Calendar}s
. - *getCalendarNames() throws SchedulerException; /** - * - * Request the interruption of all currently executing instances of the - * identified
+ * Request the interruption, within this Scheduler instance, of all + * currently executing instances of the identifiedJob
, which must be an implementor of the - *InterruptableJob
interface. - *Job
, which + * must be an implementor of theInterruptableJob
interface. * ** If more than one instance of the identified job is currently executing, @@ -780,198 +882,73 @@ *
* *- * If you wish to interrupt a specific instance of a job (when more than - * one is executing) you can do so by calling - *
* - * @param jobName - * @param groupName - * @return true is at least one instance of the identified job was found + * @return true if at least one instance of the identified job was found * and interrupted. * @throws UnableToInterruptJobException if the job does not implement *{@link #getCurrentlyExecutingJobs()}
to obtain a handle - * to the job instance, and then invokeinterrupt()
on it - * yourself. + * This method is not cluster aware. That is, it will only interrupt + * instances of the identified InterruptableJob currently executing in this + * Scheduler instance, not across the entire cluster. *InterruptableJob
, or there is an exception while * interrupting the job. * @see InterruptableJob#interrupt() * @see #getCurrentlyExecutingJobs() + * @see #interrupt(String) */ - public boolean interrupt(String jobName, String groupName) throws UnableToInterruptJobException; + boolean interrupt(JobKey jobKey) throws UnableToInterruptJobException; - /////////////////////////////////////////////////////////////////////////// - /// - /// Listener-related Methods - /// - /////////////////////////////////////////////////////////////////////////// - /** - *- * Add the given
+ * Request the interruption, within this Scheduler instance, of the + * identified executing{@link JobListener}
to theScheduler
's - * global list. - *Job
instance, which + * must be an implementor of theInterruptableJob
interface. * *- * Listeners in the 'global' list receive notification of execution events - * for ALL
- */ - public void addGlobalJobListener(JobListener jobListener) - throws SchedulerException; - - /** - *{@link org.quartz.JobDetail}
s. + * This method is not cluster aware. That is, it will only interrupt + * instances of the identified InterruptableJob currently executing in this + * Scheduler instance, not across the entire cluster. *- * Add the given
{@link JobListener}
to theScheduler
's - * list, of registeredJobListener
s. - */ - public void addJobListener(JobListener jobListener) - throws SchedulerException; - - /** - *- * Remove the given
* - * @return true if the identifed listener was found in the list, and - * removed. + * @param fireInstanceId the unique identifier of the job instance to + * be interrupted (see {@link JobExecutionContext#getFireInstanceId()} + * @return true if the identified job instance was found and interrupted. + * @throws UnableToInterruptJobException if the job does not implement + *{@link JobListener}
from theScheduler
's - * list of global listeners. - *InterruptableJob
, or there is an exception while + * interrupting the job. + * @see InterruptableJob#interrupt() + * @see #getCurrentlyExecutingJobs() + * @see JobExecutionContext#getFireInstanceId() + * @see #interrupt(JobKey) */ - public boolean removeGlobalJobListener(JobListener jobListener) - throws SchedulerException; - + boolean interrupt(String fireInstanceId) throws UnableToInterruptJobException; + /** - *- * Remove the identifed
+ * Determine whether a {@link Job} with the given identifier already + * exists within the scheduler. * - * @return true if the identifed listener was found in the list, and - * removed. + * @param jobKey the identifier to check for + * @return true if a Job exists with the given identifier + * @throws SchedulerException */ - public boolean removeJobListener(String name) throws SchedulerException; - + boolean checkExists(JobKey jobKey) throws SchedulerException; + /** - *{@link JobListener}
from theScheduler
's - * list of registered listeners. - *- * Get a List containing all of the
- */ - public List getGlobalJobListeners() throws SchedulerException; - - /** - *{@link JobListener}
s in - * theScheduler
'sglobal list. - *- * Get a Set containing the names of all the non-global
- */ - public Set getJobListenerNames() throws SchedulerException; - - /** - *{@link JobListener}
- * s registered with theScheduler
. - *- * Get the non-global
- */ - public JobListener getJobListener(String name) throws SchedulerException; - - /** - *{@link JobListener}
that has - * the given name. - *- * Add the given
+ * Determine whether a {@link Trigger} with the given identifier already + * exists within the scheduler. * - *{@link TriggerListener}
to theScheduler
's - * global list. - *- * Listeners in the 'global' list receive notification of execution events - * for ALL
+ * @param triggerKey the identifier to check for + * @return true if a Trigger exists with the given identifier + * @throws SchedulerException */ - public void addGlobalTriggerListener(TriggerListener triggerListener) - throws SchedulerException; - + boolean checkExists(TriggerKey triggerKey) throws SchedulerException; + /** - *{@link Trigger}
s. - *- * Add the given
{@link TriggerListener}
to theScheduler
's - * list, of registeredTriggerListener
s. - */ - public void addTriggerListener(TriggerListener triggerListener) - throws SchedulerException; - - /** - *- * Remove the given
+ * Clears (deletes!) all scheduling data - all {@link Job}s, {@link Trigger}s + * {@link Calendar}s. * - * @return true if the identifed listener was found in the list, and - * removed. + * @throws SchedulerException */ - public boolean removeGlobalTriggerListener(TriggerListener triggerListener) - throws SchedulerException; + void clear() throws SchedulerException; - /** - *{@link TriggerListener}
from theScheduler
's - * list of global listeners. - *- * Remove the identifed
- * - * @return true if the identifed listener was found in the list, and - * removed. - */ - public boolean removeTriggerListener(String name) throws SchedulerException; - /** - *{@link TriggerListener}
from the - *Scheduler
's list of registered listeners. - *- * Get a List containing all of the
- */ - public List getGlobalTriggerListeners() throws SchedulerException; - - /** - *{@link TriggerListener}
- * s in theScheduler
'sglobal list. - *- * Get a Set containing the names of all the non-global
- */ - public Set getTriggerListenerNames() throws SchedulerException; - - /** - *{@link TriggerListener}
- * s registered with theScheduler
. - *- * Get the non-global
- */ - public TriggerListener getTriggerListener(String name) - throws SchedulerException; - - /** - *{@link TriggerListener}
that - * has the given name. - *- * Register the given
- */ - public void addSchedulerListener(SchedulerListener schedulerListener) - throws SchedulerException; - - /** - *{@link SchedulerListener}
with the - *Scheduler
. - *- * Remove the given
- * - * @return true if the identifed listener was found in the list, and - * removed. - */ - public boolean removeSchedulerListener(SchedulerListener schedulerListener) - throws SchedulerException; - - /** - *{@link SchedulerListener}
from the - *Scheduler
. - *- * Get a List containing all of the
- */ - public List getSchedulerListeners() throws SchedulerException; - - } Index: 3rdParty_sources/quartz/org/quartz/SchedulerConfigException.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/SchedulerConfigException.java (.../SchedulerConfigException.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/SchedulerConfigException.java (.../SchedulerConfigException.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,21 +16,18 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; /** - *{@link SchedulerListener}
- * s registered with theScheduler
. - ** An exception that is thrown to indicate that there is a misconfiguration of * the
* * @author James House */ public class SchedulerConfigException extends SchedulerException { + + private static final long serialVersionUID = -5921239824646083098L; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -46,7 +43,7 @@ * */ public SchedulerConfigException(String msg) { - super(msg, ERR_BAD_CONFIGURATION); + super(msg); } /** @@ -55,9 +52,8 @@ * and cause. * */ - public SchedulerConfigException(String msg, Exception cause) { + public SchedulerConfigException(String msg, Throwable cause) { super(msg, cause); - setErrorCode(ERR_BAD_CONFIGURATION); } } Index: 3rdParty_sources/quartz/org/quartz/SchedulerContext.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/SchedulerContext.java (.../SchedulerContext.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/SchedulerContext.java (.../SchedulerContext.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,361 +16,46 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; import java.io.Serializable; -import java.util.Iterator; import java.util.Map; -import org.quartz.utils.DirtyFlagMap; +import org.quartz.utils.StringKeyDirtyFlagMap; /** - *SchedulerFactory
- or one of the components it * configures. - ** Holds context/environment data that can be made available to Jobs as they * are executed. This feature is much like the ServletContext feature when * working with J2EE servlets. - *
* + *+ * Future versions of Quartz may make distinctions on how it propagates + * data in
+ * * @see Scheduler#getContext * * @author James House */ -public class SchedulerContext extends DirtyFlagMap implements Serializable { - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Data members. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - - private boolean allowsTransientData = false; - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Constructors. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - +public class SchedulerContext extends StringKeyDirtyFlagMap implements Serializable { + + private static final long serialVersionUID = -6659641334616491764L; + /** - *SchedulerContext
between instances of proxies to a + * single scheduler instance - i.e. if Quartz is being used via RMI. + *- * Create an empty
+ * Create an emptyJobDataMap
. - *SchedulerContext
. */ public SchedulerContext() { super(15); } /** - *- * Create a
+ * Create aJobDataMap
with the given data. - *SchedulerContext
with the given data. */ - public SchedulerContext(Map map) { + public SchedulerContext(Map, ?> map) { this(); - - putAll(map); + @SuppressWarnings("unchecked") // param must be a String key map. + MapmapTyped = (Map )map; + putAll(mapTyped); } - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Interface. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - - /** - * - * Tell the
- * - *SchedulerContext
that it should allow non- - *Serializable
data. - *- * Future versions of Quartz may make distinctions on how it propogates - * data in the SchedulerContext between instances of proxies to a single - * scheduler instance - i.e. if Quartz is being used via RMI. - *
- */ - public void setAllowsTransientData(boolean allowsTransientData) { - - if (containsTransientData() && !allowsTransientData) - throw new IllegalStateException( - "Cannot set property 'allowsTransientData' to 'false' " - + "when data map contains non-serializable objects."); - - this.allowsTransientData = allowsTransientData; - } - - public boolean getAllowsTransientData() { - return allowsTransientData; - } - - public boolean containsTransientData() { - - if (!getAllowsTransientData()) // short circuit... - return false; - - String[] keys = getKeys(); - - for (int i = 0; i < keys.length; i++) { - Object o = super.get(keys[i]); - if (!(o instanceof Serializable)) return true; - } - - return false; - } - - /** - *- * Nulls-out any data values that are non-Serializable. - *
- */ - public void removeTransientData() { - - if (!getAllowsTransientData()) // short circuit... - return; - - String[] keys = getKeys(); - - for (int i = 0; i < keys.length; i++) { - Object o = super.get(keys[i]); - if (!(o instanceof Serializable)) remove(keys[i]); - } - - } - - /** - *- * Adds the name-value pairs in the given
- * - *Map
to theSchedulerContext
. - *- * All keys must be
- */ - public void putAll(Map map) { - Iterator itr = map.keySet().iterator(); - while (itr.hasNext()) { - Object key = itr.next(); - Object val = map.get(key); - - put(key, val); - // will throw IllegalArgumentException if value not serilizable - } - } - - /** - *String
s. - *- * Adds the given
- */ - public void put(String key, int value) { - super.put(key, new Integer(value)); - } - - /** - *int
value to theSchedulerContext
. - *- * Adds the given
- */ - public void put(String key, long value) { - super.put(key, new Long(value)); - } - - /** - *long
value to theSchedulerContext
. - *- * Adds the given
- */ - public void put(String key, float value) { - super.put(key, new Float(value)); - } - - /** - *float
value to theSchedulerContext
. - *- * Adds the given
- */ - public void put(String key, double value) { - super.put(key, new Double(value)); - } - - /** - *double
value to theSchedulerContext
. - *- * Adds the given
- */ - public void put(String key, boolean value) { - super.put(key, new Boolean(value)); - } - - /** - *boolean
value to theSchedulerContext
. - *- * Adds the given
- */ - public void put(String key, char value) { - super.put(key, new Character(value)); - } - - /** - *char
value to theSchedulerContext
. - *- * Adds the given
- */ - public void put(String key, String value) { - super.put(key, value); - } - - /** - *String
value to theSchedulerContext
. - *- * Adds the given
- */ - public Object put(Object key, Object value) { - if (!(key instanceof String)) - throw new IllegalArgumentException( - "Keys in map must be Strings."); - - return super.put(key, value); - } - - /** - *Object
value to theSchedulerContext
. - *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not an Integer. - */ - public int getInt(String key) { - Object obj = get(key); - - try { - return ((Integer) obj).intValue(); - } catch (Exception e) { - throw new ClassCastException("Identified object is not an Integer."); - } - } - - /** - *int
value from theSchedulerContext
. - *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not a Long. - */ - public long getLong(String key) { - Object obj = get(key); - - try { - return ((Long) obj).longValue(); - } catch (Exception e) { - throw new ClassCastException("Identified object is not a Long."); - } - } - - /** - *long
value from theSchedulerContext
. - *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not a Float. - */ - public float getFloat(String key) { - Object obj = get(key); - - try { - return ((Float) obj).floatValue(); - } catch (Exception e) { - throw new ClassCastException("Identified object is not a Float."); - } - } - - /** - *float
value from theSchedulerContext
. - *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not a Double. - */ - public double getDouble(String key) { - Object obj = get(key); - - try { - return ((Double) obj).doubleValue(); - } catch (Exception e) { - throw new ClassCastException("Identified object is not a Double."); - } - } - - /** - *double
value from theSchedulerContext
. - *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not a Boolean. - */ - public boolean getBoolean(String key) { - Object obj = get(key); - - try { - return ((Boolean) obj).booleanValue(); - } catch (Exception e) { - throw new ClassCastException("Identified object is not a Boolean."); - } - } - - /** - *boolean
value from theSchedulerContext
. - *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not a Character. - */ - public char getChar(String key) { - Object obj = get(key); - - try { - return ((Character) obj).charValue(); - } catch (Exception e) { - throw new ClassCastException( - "Identified object is not a Character."); - } - } - - /** - *char
value from theSchedulerContext
. - *- * Retrieve the identified
- * - * @throws ClassCastException - * if the identified object is not a String. - */ - public String getString(String key) { - Object obj = get(key); - - try { - return (String) obj; - } catch (Exception e) { - throw new ClassCastException("Identified object is not a String."); - } - } - - public String[] getKeys() { - return (String[]) keySet().toArray(new String[size()]); - } - } Index: 3rdParty_sources/quartz/org/quartz/SchedulerException.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/SchedulerException.java (.../SchedulerException.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/SchedulerException.java (.../SchedulerException.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,91 +16,27 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; -import java.io.PrintStream; -import java.io.PrintWriter; + /** - *String
value from theSchedulerContext
. - ** Base class for exceptions thrown by the Quartz
* *{@link Scheduler}
. - *- *
* * @author James House */ public class SchedulerException extends Exception { + + private static final long serialVersionUID = 174841398690789156L; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * Constants. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - - public static final int ERR_UNSPECIFIED = 0; - - public static final int ERR_BAD_CONFIGURATION = 50; - - public static final int ERR_TIME_BROKER_FAILURE = 70; - - public static final int ERR_CLIENT_ERROR = 100; - - public static final int ERR_COMMUNICATION_FAILURE = 200; - - public static final int ERR_UNSUPPORTED_FUNCTION_IN_THIS_CONFIGURATION = 210; - - public static final int ERR_PERSISTENCE = 400; - - public static final int ERR_PERSISTENCE_JOB_DOES_NOT_EXIST = 410; - - public static final int ERR_PERSISTENCE_CALENDAR_DOES_NOT_EXIST = 420; - - public static final int ERR_PERSISTENCE_TRIGGER_DOES_NOT_EXIST = 430; - - public static final int ERR_PERSISTENCE_CRITICAL_FAILURE = 499; - - public static final int ERR_THREAD_POOL = 500; - - public static final int ERR_THREAD_POOL_EXHAUSTED = 510; - - public static final int ERR_THREAD_POOL_CRITICAL_FAILURE = 599; - - public static final int ERR_JOB_LISTENER = 600; - - public static final int ERR_JOB_LISTENER_NOT_FOUND = 610; - - public static final int ERR_TRIGGER_LISTENER = 700; - - public static final int ERR_TRIGGER_LISTENER_NOT_FOUND = 710; - - public static final int ERR_JOB_EXECUTION_THREW_EXCEPTION = 800; - - public static final int ERR_TRIGGER_THREW_EXCEPTION = 850; - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Data members. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - - private Exception cause; - - private int errorCode = ERR_UNSPECIFIED; - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * * Constructors. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -114,27 +50,16 @@ super(msg); } - public SchedulerException(String msg, int errorCode) { - super(msg); - setErrorCode(errorCode); + public SchedulerException(Throwable cause) { + super(cause); } - public SchedulerException(Exception cause) { - super(cause.toString()); - this.cause = cause; + public SchedulerException(String msg, Throwable cause) { + super(msg, cause); } - public SchedulerException(String msg, Exception cause) { - super(msg); - this.cause = cause; - } - public SchedulerException(String msg, Exception cause, int errorCode) { - super(msg); - this.cause = cause; - setErrorCode(errorCode); - } - + /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -156,167 +81,18 @@ * one. */ public Throwable getUnderlyingException() { - return cause; + return super.getCause(); } - /** - *SchedulerException
s may contain a reference to another + *SchedulerException
s may contain a reference to another *Exception
, which was the underlying cause of theSchedulerException
. *- * Get the error code associated with this exception. - *
- * - *- * This may be used to find more detail about the cause of the error. - *
- * - * @return one of the ERR_XXX constants defined in this class. - */ - public int getErrorCode() { - return errorCode; - } - - /** - *- * Get the error code associated with this exception. - *
- * - *- * This may be used to provide more detail about the cause of the error. - *
- * - * @param errorCode - * one of the ERR_XXX constants defined in this class. - */ - public void setErrorCode(int errorCode) { - this.errorCode = errorCode; - } - - /** - *- * Determine if the specified error code is in the
- */ - public boolean isPersistenceError() { - return (errorCode >= ERR_PERSISTENCE && errorCode <= ERR_PERSISTENCE + 99); - } - - /** - *'ERR_PERSISTENCE'
- * category of errors. - *- * Determine if the specified error code is in the
- */ - public boolean isThreadPoolError() { - return (errorCode >= ERR_THREAD_POOL && errorCode <= ERR_THREAD_POOL + 99); - } - - /** - *'ERR_THREAD_POOL'
- * category of errors. - *- * Determine if the specified error code is in the
- */ - public boolean isJobListenerError() { - return (errorCode >= ERR_JOB_LISTENER && errorCode <= ERR_JOB_LISTENER + 99); - } - - /** - *'ERR_JOB_LISTENER'
- * category of errors. - *- * Determine if the specified error code is in the
- */ - public boolean isTriggerListenerError() { - return (errorCode >= ERR_TRIGGER_LISTENER && errorCode <= ERR_TRIGGER_LISTENER + 99); - } - - /** - *'ERR_TRIGGER_LISTENER'
- * category of errors. - *- * Determine if the specified error code is in the
- */ - public boolean isClientError() { - return (errorCode >= ERR_CLIENT_ERROR && errorCode <= ERR_CLIENT_ERROR + 99); - } - - /** - *'ERR_CLIENT_ERROR'
- * category of errors. - *- * Determine if the specified error code is in the
- */ - public boolean isConfigurationError() { - return (errorCode >= ERR_BAD_CONFIGURATION && errorCode <= ERR_BAD_CONFIGURATION + 49); - } - + @Override public String toString() { - if (cause == null) return super.toString(); - else - return super.toString() + " [See nested exception: " - + cause.toString() + "]"; - } - - /** - *'ERR_CLIENT_ERROR'
- * category of errors. - *- * Print a stack trace to the standard error stream. - *
- * - *- * This overridden version will print the nested stack trace if available, - * otherwise it prints only this exception's stack. - *
- */ - public void printStackTrace() { - printStackTrace(System.err); - } - - /** - *- * Print a stack trace to the specified stream. - *
- * - *- * This overridden version will print the nested stack trace if available, - * otherwise it prints only this exception's stack. - *
- * - * @param out - * the stream to which the stack traces will be printed. - */ - public void printStackTrace(PrintStream out) { - super.printStackTrace(out); - if ((cause != null)) { - synchronized (out) { - out - .println("* Nested Exception (Underlying Cause) ---------------"); - cause.printStackTrace(out); - } + Throwable cause = getUnderlyingException(); + if (cause == null || cause == this) { + return super.toString(); + } else { + return super.toString() + " [See nested exception: " + cause + "]"; } } - /** - *- * Print a stack trace to the specified writer. - *
- * - *- * This overridden version will print the nested stack trace if available, - * otherwise it prints this exception's stack. - *
- * - * @param out - * the writer to which the stack traces will be printed. - */ - public void printStackTrace(PrintWriter out) { - super.printStackTrace(out); - if ((cause != null)) { - synchronized (out) { - out - .println("* Nested Exception (Underlying Cause) ---------------"); - cause.printStackTrace(out); - } - } - } } Index: 3rdParty_sources/quartz/org/quartz/SchedulerFactory.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/SchedulerFactory.java (.../SchedulerFactory.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/SchedulerFactory.java (.../SchedulerFactory.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,18 +16,13 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; import java.util.Collection; /** - ** Provides a mechanism for obtaining client-usable handles to
* * @see Scheduler * @see org.quartz.impl.StdSchedulerFactory @@ -52,21 +47,21 @@ * @throws SchedulerException * if there is a problem with the underlyingScheduler
* instances. - *Scheduler
. */ - public Scheduler getScheduler() throws SchedulerException; + Scheduler getScheduler() throws SchedulerException; /** ** Returns a handle to the Scheduler with the given name, if it exists. *
*/ - public Scheduler getScheduler(String schedName) throws SchedulerException; + Scheduler getScheduler(String schedName) throws SchedulerException; /** ** Returns handles to all known Schedulers (made by any SchedulerFactory * within this jvm.). *
*/ - public Collection getAllSchedulers() throws SchedulerException; + CollectiongetAllSchedulers() throws SchedulerException; } Index: 3rdParty_sources/quartz/org/quartz/SchedulerListener.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/SchedulerListener.java (.../SchedulerListener.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/SchedulerListener.java (.../SchedulerListener.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,16 +16,11 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; /** - * * The interface to be implemented by classes that want to be informed of major *
* * @see Scheduler * @see JobListener @@ -49,82 +44,116 @@ * is scheduled. * */ - public void jobScheduled(Trigger trigger); + void jobScheduled(Trigger trigger); /** *{@link Scheduler}
events. - ** Called by the
+ * + * @see SchedulerListener#schedulingDataCleared() */ - public void jobUnscheduled(String triggerName, String triggerGroup); + void jobUnscheduled(TriggerKey triggerKey); /** *{@link Scheduler}
when a{@link org.quartz.JobDetail}
* is unscheduled. ** Called by the
*/ - public void triggerFinalized(Trigger trigger); + void triggerFinalized(Trigger trigger); /** *{@link Scheduler}
when a{@link Trigger}
* has reached the condition in which it will never fire again. ** Called by the
- * + */ + void triggerPaused(TriggerKey triggerKey); + + /** *{@link Scheduler}
when a{@link Trigger}
- * or group of{@link Trigger}s
has been paused. + * has been paused. *- * If a group was paused, then the
+ * + *triggerName
parameter - * will be null. + * Called by the{@link Scheduler}
when a + * group of{@link Trigger}s
has been paused. *If all groups were paused then triggerGroup will be null
+ * + * @param triggerGroup the paused group, or null if all were paused */ - public void triggersPaused(String triggerName, String triggerGroup); - + void triggersPaused(String triggerGroup); + /** ** Called by the
- * + */ + void triggerResumed(TriggerKey triggerKey); + + /** *{@link Scheduler}
when a{@link Trigger}
- * or group of{@link Trigger}s
has been un-paused. + * has been un-paused. *- * If a group was resumed, then the
*/ - public void triggersResumed(String triggerName, String triggerGroup); + void triggersResumed(String triggerGroup); /** *triggerName
parameter - * will be null. + * Called by the{@link Scheduler}
when a + * group of{@link Trigger}s
has been un-paused. ** Called by the
- * + */ + void jobAdded(JobDetail jobDetail); + + /** *{@link Scheduler}
when a{@link org.quartz.JobDetail}
- * or group of{@link org.quartz.JobDetail}s
has been - * paused. + * has been added. *- * If a group was paused, then the
*/ - public void jobsPaused(String jobName, String jobGroup); - + void jobDeleted(JobKey jobKey); + /** *jobName
parameter will be - * null. If all jobs were paused, then both parameters will be null. + * Called by the{@link Scheduler}
when a{@link org.quartz.JobDetail}
+ * has been deleted. ** Called by the
+ */ + void jobPaused(JobKey jobKey); + + /** + *{@link Scheduler}
when a{@link org.quartz.JobDetail}
- * or group of{@link org.quartz.JobDetail}s
has been - * un-paused. + * has been paused. *+ * Called by the
* + * @param jobGroup the paused group, or null if all were paused + */ + void jobsPaused(String jobGroup); + + /** *{@link Scheduler}
when a + * group of{@link org.quartz.JobDetail}s
has been paused. + *- * If a group was resumed, then the
*/ - public void jobsResumed(String jobName, String jobGroup); + void jobResumed(JobKey jobKey); /** *jobName
parameter will - * be null. If all jobs were paused, then both parameters will be null. + * Called by the{@link Scheduler}
when a{@link org.quartz.JobDetail}
+ * has been un-paused. *+ * Called by the
+ */ + void jobsResumed(String jobGroup); + + /** + *{@link Scheduler}
when a + * group of{@link org.quartz.JobDetail}s
has been un-paused. + ** Called by the
@@ -135,14 +164,51 @@ * error that was encountered. * */ - public void schedulerError(String msg, SchedulerException cause); + void schedulerError(String msg, SchedulerException cause); /** *{@link Scheduler}
when a serious error has - * occured within the scheduler - such as repeated failures in theJobStore
, + * occurred within the scheduler - such as repeated failures in theJobStore
, * or the inability to instantiate aJob
instance when its *Trigger
has fired. ** Called by the
+ */ + void schedulerInStandbyMode(); + + /** + *{@link Scheduler}
to inform the listener + * that it has move to standby mode. + *+ * Called by the
+ */ + void schedulerStarted(); + + /** + *{@link Scheduler}
to inform the listener + * that it has started. + *+ * Called by the
+ */ + void schedulerStarting(); + + /** + *{@link Scheduler}
to inform the listener + * that it is starting. + *+ * Called by the
*/ - public void schedulerShutdown(); + void schedulerShutdown(); + + /** + *{@link Scheduler}
to inform the listener * that it has shutdown. *+ * Called by the
+ */ + void schedulerShuttingdown(); + /** + * Called by the{@link Scheduler}
to inform the listener + * that it has begun the shutdown sequence. + *{@link Scheduler}
to inform the listener + * that all jobs, triggers and calendars were deleted. + */ + void schedulingDataCleared(); } Index: 3rdParty_sources/quartz/org/quartz/SchedulerMetaData.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/SchedulerMetaData.java (.../SchedulerMetaData.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/SchedulerMetaData.java (.../SchedulerMetaData.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,22 +16,19 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; import java.util.Date; /** - ** Describes the settings and capabilities of a given
* * @author James House */ public class SchedulerMetaData implements java.io.Serializable { + + private static final long serialVersionUID = 4203690002633917647L; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -45,26 +42,28 @@ private String schedInst; - private Class schedClass; + private Class> schedClass; private boolean isRemote; private boolean started; - private boolean paused; + private boolean isInStandbyMode; private boolean shutdown; private Date startTime; private int numJobsExec; - private Class jsClass; + private Class> jsClass; private boolean jsPersistent; - private Class tpClass; + private boolean jsClustered; + private Class> tpClass; + private int tpSize; private String version; @@ -78,21 +77,22 @@ */ public SchedulerMetaData(String schedName, String schedInst, - Class schedClass, boolean isRemote, boolean started, - boolean paused, boolean shutdown, Date startTime, int numJobsExec, - Class jsClass, boolean jsPersistent, Class tpClass, int tpSize, + Class> schedClass, boolean isRemote, boolean started, + boolean isInStandbyMode, boolean shutdown, Date startTime, int numJobsExec, + Class> jsClass, boolean jsPersistent, boolean jsClustered, Class> tpClass, int tpSize, String version) { this.schedName = schedName; this.schedInst = schedInst; this.schedClass = schedClass; this.isRemote = isRemote; this.started = started; - this.paused = paused; + this.isInStandbyMode = isInStandbyMode; this.shutdown = shutdown; this.startTime = startTime; this.numJobsExec = numJobsExec; this.jsClass = jsClass; this.jsPersistent = jsPersistent; + this.jsClustered = jsClustered; this.tpClass = tpClass; this.tpSize = tpSize; this.version = version; @@ -129,7 +129,7 @@ * Returns the class-name of the{@link Scheduler}
* instance. - *Scheduler
instance. * */ - public Class getSchedulerClass() { + public Class> getSchedulerClass() { return schedClass; } @@ -140,17 +140,17 @@ * * @return null if the scheduler has not been started. */ - public Date runningSince() { + public Date getRunningSince() { return startTime; } - + /** ** Returns the number of jobs executed since the
*/ - public int numJobsExecuted() { + public int getNumberOfJobsExecuted() { return numJobsExec; } @@ -171,25 +171,18 @@ * *Scheduler
* started.. ** Note:
*/ public boolean isStarted() { return started; } /** - *isStarted()
may returntrue
even if - *isPaused()
returnstrue
. + *isInStandbyMode()
returnstrue
. *- * Reports whether the
- * - *Scheduler
is paused. - *- * Note:
+ * Reports whether theisStarted()
may returntrue
even if - *isPaused()
returnstrue
. - *Scheduler
is in standby mode. */ - public boolean isPaused() { - return paused; + public boolean isInStandbyMode() { + return isInStandbyMode; } /** @@ -207,27 +200,37 @@ * being used by theScheduler
. * */ - public Class getJobStoreClass() { + public Class> getJobStoreClass() { return jsClass; } - + /** ** Returns whether or not the
*/ - public boolean jobStoreSupportsPersistence() { + public boolean isJobStoreSupportsPersistence() { return jsPersistent; } /** *Scheduler
'sJobStore
* instance supports persistence. *+ * Returns whether or not the
+ */ + public boolean isJobStoreClustered() { + return jsClustered; + } + + /** + *Scheduler
'sJobStore
+ * is clustered. + ** Returns the class-name of the
*/ - public Class getThreadPoolClass() { + public Class> getThreadPoolClass() { return tpClass; } @@ -255,6 +258,7 @@ * Return a simple string representation of this object. * */ + @Override public String toString() { try { return getSummary(); @@ -281,7 +285,7 @@ * */ public String getSummary() throws SchedulerException { - StringBuffer str = new StringBuffer("Quartz Scheduler (v"); + StringBuilder str = new StringBuilder("Quartz Scheduler (v"); str.append(getVersion()); str.append(") '"); @@ -293,29 +297,34 @@ str.append(" Scheduler class: '"); str.append(getSchedulerClass().getName()); str.append("'"); - if (isSchedulerRemote()) str.append(" - access via RMI."); - else + if (isSchedulerRemote()) { + str.append(" - access via RMI."); + } else { str.append(" - running locally."); + } str.append("\n"); if (!isShutdown()) { - if (runningSince() != null) { + if (getRunningSince() != null) { str.append(" Running since: "); - str.append(runningSince()); - } else - str.append("NOT STARTED."); + str.append(getRunningSince()); + } else { + str.append(" NOT STARTED."); + } str.append("\n"); - if (isPaused()) str.append(" Currently PAUSED."); - else - str.append(" Not currently paused."); + if (isInStandbyMode()) { + str.append(" Currently in standby mode."); + } else { + str.append(" Not currently in standby mode."); + } } else { str.append(" Scheduler has been SHUTDOWN."); } str.append("\n"); str.append(" Number of jobs executed: "); - str.append(numJobsExecuted()); + str.append(getNumberOfJobsExecuted()); str.append("\n"); str.append(" Using thread pool '"); @@ -328,9 +337,16 @@ str.append(" Using job-store '"); str.append(getJobStoreClass().getName()); str.append("' - which "); - if (jobStoreSupportsPersistence()) str.append("supports persistence."); - else + if (isJobStoreSupportsPersistence()) { + str.append("supports persistence."); + } else { str.append("does not support persistence."); + } + if (isJobStoreClustered()) { + str.append(" and is clustered."); + } else { + str.append(" and is not clustered."); + } str.append("\n"); return str.toString(); Index: 3rdParty_sources/quartz/org/quartz/SimpleScheduleBuilder.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/SimpleScheduleBuilder.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/SimpleScheduleBuilder.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,429 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import org.quartz.impl.triggers.SimpleTriggerImpl; +import org.quartz.spi.MutableTrigger; + +/** + *ThreadPool
instance that is * being used by theScheduler
. *SimpleScheduleBuilder
is a {@link ScheduleBuilder} + * that defines strict/literal interval-based schedules for + *Trigger
s. + * + *Quartz provides a builder-style API for constructing scheduling-related + * entities via a Domain-Specific Language (DSL). The DSL can best be + * utilized through the usage of static imports of the methods on the classes + *
+ * + *TriggerBuilder
,JobBuilder
, + *DateBuilder
,JobKey
,TriggerKey
+ * and the variousScheduleBuilder
implementations.Client code can then use the DSL to write code such as this:
+ *+ * JobDetail job = newJob(MyJob.class) + * .withIdentity("myJob") + * .build(); + * + * Trigger trigger = newTrigger() + * .withIdentity(triggerKey("myTrigger", "myTriggerGroup")) + * .withSchedule(simpleSchedule() + * .withIntervalInHours(1) + * .repeatForever()) + * .startAt(futureDate(10, MINUTES)) + * .build(); + * + * scheduler.scheduleJob(job, trigger); + *+ * + * @see SimpleTrigger + * @see CalendarIntervalScheduleBuilder + * @see CronScheduleBuilder + * @see ScheduleBuilder + * @see TriggerBuilder + */ +public class SimpleScheduleBuilder extends ScheduleBuilder{ + + private long interval = 0; + private int repeatCount = 0; + private int misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_SMART_POLICY; + + protected SimpleScheduleBuilder() { + } + + /** + * Create a SimpleScheduleBuilder. + * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder simpleSchedule() { + return new SimpleScheduleBuilder(); + } + + /** + * Create a SimpleScheduleBuilder set to repeat forever with a 1 minute interval. + * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder repeatMinutelyForever() { + + return simpleSchedule() + .withIntervalInMinutes(1) + .repeatForever(); + } + + /** + * Create a SimpleScheduleBuilder set to repeat forever with an interval + * of the given number of minutes. + * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder repeatMinutelyForever(int minutes) { + + return simpleSchedule() + .withIntervalInMinutes(minutes) + .repeatForever(); + } + + /** + * Create a SimpleScheduleBuilder set to repeat forever with a 1 second interval. + * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder repeatSecondlyForever() { + + return simpleSchedule() + .withIntervalInSeconds(1) + .repeatForever(); + } + + /** + * Create a SimpleScheduleBuilder set to repeat forever with an interval + * of the given number of seconds. + * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder repeatSecondlyForever(int seconds) { + + return simpleSchedule() + .withIntervalInSeconds(seconds) + .repeatForever(); + } + + /** + * Create a SimpleScheduleBuilder set to repeat forever with a 1 hour interval. + * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder repeatHourlyForever() { + + return simpleSchedule() + .withIntervalInHours(1) + .repeatForever(); + } + + /** + * Create a SimpleScheduleBuilder set to repeat forever with an interval + * of the given number of hours. + * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder repeatHourlyForever(int hours) { + + return simpleSchedule() + .withIntervalInHours(hours) + .repeatForever(); + } + + /** + * Create a SimpleScheduleBuilder set to repeat the given number + * of times - 1 with a 1 minute interval. + * + * Note: Total count = 1 (at start time) + repeat count
+ * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder repeatMinutelyForTotalCount(int count) { + if(count < 1) + throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count); + + return simpleSchedule() + .withIntervalInMinutes(1) + .withRepeatCount(count - 1); + } + + /** + * Create a SimpleScheduleBuilder set to repeat the given number + * of times - 1 with an interval of the given number of minutes. + * + *Note: Total count = 1 (at start time) + repeat count
+ * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder repeatMinutelyForTotalCount(int count, int minutes) { + if(count < 1) + throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count); + + return simpleSchedule() + .withIntervalInMinutes(minutes) + .withRepeatCount(count - 1); + } + + /** + * Create a SimpleScheduleBuilder set to repeat the given number + * of times - 1 with a 1 second interval. + * + *Note: Total count = 1 (at start time) + repeat count
+ * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder repeatSecondlyForTotalCount(int count) { + if(count < 1) + throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count); + + return simpleSchedule() + .withIntervalInSeconds(1) + .withRepeatCount(count - 1); + } + + /** + * Create a SimpleScheduleBuilder set to repeat the given number + * of times - 1 with an interval of the given number of seconds. + * + *Note: Total count = 1 (at start time) + repeat count
+ * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder repeatSecondlyForTotalCount(int count, int seconds) { + if(count < 1) + throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count); + + return simpleSchedule() + .withIntervalInSeconds(seconds) + .withRepeatCount(count - 1); + } + + /** + * Create a SimpleScheduleBuilder set to repeat the given number + * of times - 1 with a 1 hour interval. + * + *Note: Total count = 1 (at start time) + repeat count
+ * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder repeatHourlyForTotalCount(int count) { + if(count < 1) + throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count); + + return simpleSchedule() + .withIntervalInHours(1) + .withRepeatCount(count - 1); + } + + /** + * Create a SimpleScheduleBuilder set to repeat the given number + * of times - 1 with an interval of the given number of hours. + * + *Note: Total count = 1 (at start time) + repeat count
+ * + * @return the new SimpleScheduleBuilder + */ + public static SimpleScheduleBuilder repeatHourlyForTotalCount(int count, int hours) { + if(count < 1) + throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count); + + return simpleSchedule() + .withIntervalInHours(hours) + .withRepeatCount(count - 1); + } + + /** + * Build the actual Trigger -- NOT intended to be invoked by end users, + * but will rather be invoked by a TriggerBuilder which this + * ScheduleBuilder is given to. + * + * @see TriggerBuilder#withSchedule(ScheduleBuilder) + */ + @Override + public MutableTrigger build() { + + SimpleTriggerImpl st = new SimpleTriggerImpl(); + st.setRepeatInterval(interval); + st.setRepeatCount(repeatCount); + st.setMisfireInstruction(misfireInstruction); + + return st; + } + + /** + * Specify a repeat interval in milliseconds. + * + * @param intervalInMillis the number of seconds at which the trigger should repeat. + * @return the updated SimpleScheduleBuilder + * @see SimpleTrigger#getRepeatInterval() + * @see #withRepeatCount(int) + */ + public SimpleScheduleBuilder withIntervalInMilliseconds(long intervalInMillis) { + this.interval = intervalInMillis; + return this; + } + + /** + * Specify a repeat interval in seconds - which will then be multiplied + * by 1000 to produce milliseconds. + * + * @param intervalInSeconds the number of seconds at which the trigger should repeat. + * @return the updated SimpleScheduleBuilder + * @see SimpleTrigger#getRepeatInterval() + * @see #withRepeatCount(int) + */ + public SimpleScheduleBuilder withIntervalInSeconds(int intervalInSeconds) { + this.interval = intervalInSeconds * 1000L; + return this; + } + + /** + * Specify a repeat interval in minutes - which will then be multiplied + * by 60 * 1000 to produce milliseconds. + * + * @param intervalInMinutes the number of seconds at which the trigger should repeat. + * @return the updated SimpleScheduleBuilder + * @see SimpleTrigger#getRepeatInterval() + * @see #withRepeatCount(int) + */ + public SimpleScheduleBuilder withIntervalInMinutes(int intervalInMinutes) { + this.interval = intervalInMinutes * DateBuilder.MILLISECONDS_IN_MINUTE; + return this; + } + + /** + * Specify a repeat interval in minutes - which will then be multiplied + * by 60 * 60 * 1000 to produce milliseconds. + * + * @param intervalInHours the number of seconds at which the trigger should repeat. + * @return the updated SimpleScheduleBuilder + * @see SimpleTrigger#getRepeatInterval() + * @see #withRepeatCount(int) + */ + public SimpleScheduleBuilder withIntervalInHours(int intervalInHours) { + this.interval = intervalInHours * DateBuilder.MILLISECONDS_IN_HOUR; + return this; + } + + /** + * Specify a the number of time the trigger will repeat - total number of + * firings will be this number + 1. + * + * @param triggerRepeatCount the number of seconds at which the trigger should repeat. + * @return the updated SimpleScheduleBuilder + * @see SimpleTrigger#getRepeatCount() + * @see #repeatForever() + */ + public SimpleScheduleBuilder withRepeatCount(int triggerRepeatCount) { + this.repeatCount = triggerRepeatCount; + return this; + } + + /** + * Specify that the trigger will repeat indefinitely. + * + * @return the updated SimpleScheduleBuilder + * @see SimpleTrigger#getRepeatCount() + * @see SimpleTrigger#REPEAT_INDEFINITELY + * @see #withIntervalInMilliseconds(long) + * @see #withIntervalInSeconds(int) + * @see #withIntervalInMinutes(int) + * @see #withIntervalInHours(int) + */ + public SimpleScheduleBuilder repeatForever() { + this.repeatCount = SimpleTrigger.REPEAT_INDEFINITELY; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link Trigger#MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY} instruction. + * + * @return the updated CronScheduleBuilder + * @see Trigger#MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY + */ + public SimpleScheduleBuilder withMisfireHandlingInstructionIgnoreMisfires() { + misfireInstruction = Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link SimpleTrigger#MISFIRE_INSTRUCTION_FIRE_NOW} instruction. + * + * @return the updated SimpleScheduleBuilder + * @see SimpleTrigger#MISFIRE_INSTRUCTION_FIRE_NOW + */ + + public SimpleScheduleBuilder withMisfireHandlingInstructionFireNow() { + misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link SimpleTrigger#MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT} instruction. + * + * @return the updated SimpleScheduleBuilder + * @see SimpleTrigger#MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT + */ + public SimpleScheduleBuilder withMisfireHandlingInstructionNextWithExistingCount() { + misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link SimpleTrigger#MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT} instruction. + * + * @return the updated SimpleScheduleBuilder + * @see SimpleTrigger#MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT + */ + public SimpleScheduleBuilder withMisfireHandlingInstructionNextWithRemainingCount() { + misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link SimpleTrigger#MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT} instruction. + * + * @return the updated SimpleScheduleBuilder + * @see SimpleTrigger#MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT + */ + public SimpleScheduleBuilder withMisfireHandlingInstructionNowWithExistingCount() { + misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT; + return this; + } + + /** + * If the Trigger misfires, use the + * {@link SimpleTrigger#MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT} instruction. + * + * @return the updated SimpleScheduleBuilder + * @see SimpleTrigger#MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT + */ + public SimpleScheduleBuilder withMisfireHandlingInstructionNowWithRemainingCount() { + misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT; + return this; + } + +} Index: 3rdParty_sources/quartz/org/quartz/SimpleTrigger.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/SimpleTrigger.java (.../SimpleTrigger.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/SimpleTrigger.java (.../SimpleTrigger.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,5 @@ - -/* - * Copyright 2004-2005 OpenSymphony +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,37 +15,22 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; -import java.util.Date; - - /** - *- * A concrete
* - * @see Trigger - * @see CronTrigger - * @see TriggerUtils + * @see TriggerBuilder + * @see SimpleScheduleBuilder * * @author James House * @author contributions by Lieven Govaerts of Ebitec Nv, Belgium. */ -public class SimpleTrigger extends Trigger { +public interface SimpleTrigger extends Trigger { - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Constants. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - + public static final long serialVersionUID = -3735980074222850397L; + /** *{@link Trigger}
that is used to fire a{@link org.quartz.JobDetail}
+ * A{@link Trigger}
that is used to fire aJob
* at a given moment in time, and optionally repeated at a specified interval. - ** Instructs the
*/ public static final int MISFIRE_INSTRUCTION_FIRE_NOW = 1; - + /** *{@link Scheduler}
that upon a mis-fire @@ -62,13 +46,15 @@ ** Instructs the
* *{@link Scheduler}
that upon a mis-fire * situation, the{@link SimpleTrigger}
wants to be * re-scheduled to 'now' (even if the associated{@link Calendar}
- * excludes 'now') with the repeat count left as-is. + * excludes 'now') with the repeat count left as-is. This does obey the + *Trigger
end-time however, so if 'now' is after the + * end-time theTrigger
will not fire again. *@@ -77,29 +63,27 @@ * is only an issue if you for some reason wanted to be able to tell what * the original values were at some later time). *
- * - *- * NOTE: This instruction could cause the
*/ public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT = 2; - + /** *Trigger
- * to go to the 'COMPLETE' state after firing 'now', if all the - * repeat-fire-times where missed. - ** Instructs the
* *{@link Scheduler}
that upon a mis-fire * situation, the{@link SimpleTrigger}
wants to be * re-scheduled to 'now' (even if the associated{@link Calendar}
* excludes 'now') with the repeat count set to what it would be, if it had - * not missed any firings. + * not missed any firings. This does obey theTrigger
end-time + * however, so if 'now' is after the end-time theTrigger
will + * not fire again. ** NOTE: Use of this instruction causes the trigger to 'forget' - * the start-time and repeat-count that it was originally setup with (this - * is only an issue if you for some reason wanted to be able to tell what - * the original values were at some later time). + * the start-time and repeat-count that it was originally setup with. + * Instead, the repeat count on the trigger will be changed to whatever + * the remaining repeat count is (this is only an issue if you for some + * reason wanted to be able to tell what the original values were at some + * later time). *
* *@@ -109,7 +93,7 @@ *
*/ public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT = 3; - + /** ** Instructs the
*/ public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT = 4; - + /** *{@link Scheduler}
that upon a mis-fire @@ -125,7 +109,7 @@ ** Instructs the
* *{@link Scheduler}
that upon a mis-fire @@ -136,705 +120,45 @@ *- * NOTE: Use of this instruction causes the trigger to 'forget' - * the repeat-count that it was originally setup with (this is only an - * issue if you for some reason wanted to be able to tell what the original - * values were at some later time). - *
- * - ** NOTE/WARNING: This instruction could cause the
*/ public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT = 5; - + /** *Trigger
- * to go directly to the 'COMPLETE' state if all fire-times where missed. + * to go directly to the 'COMPLETE' state if the end-time of the trigger + * has arrived. ** Used to indicate the 'repeat count' of the trigger is indefinite. Or in * other words, the trigger should repeat continually until the trigger's * ending timestamp. *
*/ - public static int REPEAT_INDEFINITELY = -1; + public static final int REPEAT_INDEFINITELY = -1; - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Data members. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - - private Date startTime = null; - - private Date endTime = null; - - private Date nextFireTime = null; - - private Date previousFireTime = null; - - private int repeatCount = 0; - - private long repeatInterval = 0; - - private int timesTriggered = 0; - - private boolean complete = false; - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Constructors. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - /** *- * Create a
- */ - public SimpleTrigger() { - super(); - } - - /** - *SimpleTrigger
with no settings. - *- * Create a
- */ - public SimpleTrigger(String name, String group) { - this(name, group, new Date(), null, 0, 0); - } - - /** - *SimpleTrigger
that will occur immediately, and - * not repeat. - *- * Create a
- */ - public SimpleTrigger(String name, String group, int repeatCount, - long repeatInterval) { - this(name, group, new Date(), null, repeatCount, repeatInterval); - } - - /** - *SimpleTrigger
that will occur immediately, and - * repeat at the the given interval the given number of times. - *- * Create a
- */ - public SimpleTrigger(String name, String group, Date startTime) { - this(name, group, startTime, null, 0, 0); - } - - /** - *SimpleTrigger
that will occur at the given time, - * and not repeat. - *- * Create a
- * - * @param startTime - * ASimpleTrigger
that will occur at the given time, - * and repeat at the the given interval the given number of times, or until - * the given end time. - *Date
set to the time for theTrigger
- * to fire. - * @param endTime - * ADate
set to the time for theTrigger
- * to quit repeat firing. - * @param repeatCount - * The number of times for theTrigger
to repeat - * firing, use {@link #REPEAT_INDEFINITELY}for unlimitted times. - * @param repeatInterval - * The number of milliseconds to pause between the repeat firing. - */ - public SimpleTrigger(String name, String group, Date startTime, - Date endTime, int repeatCount, long repeatInterval) { - super(name, group); - - setStartTime(startTime); - setEndTime(endTime); - setRepeatCount(repeatCount); - setRepeatInterval(repeatInterval); - } - - /** - *- * Create a
- * - * @param startTime - * ASimpleTrigger
that will occur at the given time, - * fire the identifiedJob
and repeat at the the given - * interval the given number of times, or until the given end time. - *Date
set to the time for theTrigger
- * to fire. - * @param endTime - * ADate
set to the time for theTrigger
- * to quit repeat firing. - * @param repeatCount - * The number of times for theTrigger
to repeat - * firing, use {@link #REPEAT_INDEFINITELY}for unlimitted times. - * @param repeatInterval - * The number of milliseconds to pause between the repeat firing. - */ - public SimpleTrigger(String name, String group, String jobName, - String jobGroup, Date startTime, Date endTime, int repeatCount, - long repeatInterval) { - super(name, group, jobName, jobGroup); - - setStartTime(startTime); - setEndTime(endTime); - setRepeatCount(repeatCount); - setRepeatInterval(repeatInterval); - } - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Interface. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - - /** - *- * Get the time at which the
- */ - public Date getStartTime() { - return startTime; - } - - /** - *SimpleTrigger
should occur. - *- * Set the time at which the
- * - * @exception IllegalArgumentException - * if startTime isSimpleTrigger
should occur. - *null
. - */ - public void setStartTime(Date startTime) { - if (startTime == null) - throw new IllegalArgumentException("Start time cannot be null"); - - Date eTime = getEndTime(); - if (eTime != null && startTime != null && eTime.before(startTime)) - throw new IllegalArgumentException( - "End time cannot be before start time"); - - this.startTime = startTime; - } - - /** - *- * Get the time at which the
- * - * @see #getFinalFireTime() - */ - public Date getEndTime() { - return endTime; - } - - /** - *SimpleTrigger
should quit - * repeating - even if repeastCount isn't yet satisfied. - *- * Set the time at which the
- * - * @exception IllegalArgumentException - * if endTime is before start time. - */ - public void setEndTime(Date endTime) { - Date sTime = getStartTime(); - if (sTime != null && endTime != null && sTime.after(endTime)) - throw new IllegalArgumentException( - "End time cannot be before start time"); - - this.endTime = endTime; - } - - /** - *SimpleTrigger
should quit - * repeating (and be automatically deleted). - ** Get the the number of times the
* * @see #REPEAT_INDEFINITELY */ - public int getRepeatCount() { - return repeatCount; - } + public int getRepeatCount(); /** *SimpleTrigger
should * repeat, after which it will be automatically deleted. *- * Set the the number of time the
- * - * @see #REPEAT_INDEFINITELY - * @exception IllegalArgumentException - * if repeatCount is < 0 */ - public void setRepeatCount(int repeatCount) { - if (repeatCount < 0 && repeatCount != REPEAT_INDEFINITELY) - throw new IllegalArgumentException( - "Repeat count must be >= 0, use the " - + "constant REPEAT_INDEFINITELY for infinite."); - - this.repeatCount = repeatCount; - } - + public long getRepeatInterval(); + /** *SimpleTrigger
should - * repeat, after which it will be automatically deleted. + * Get the the time interval (in milliseconds) at which theSimpleTrigger
should repeat. *- * Get the the time interval (in milliseconds) at which the
*/ - public long getRepeatInterval() { - return repeatInterval; - } + public int getTimesTriggered(); - /** - *SimpleTrigger
- * should repeat. + * Get the number of times theSimpleTrigger
has already fired. *- * Set the the time interval (in milliseconds) at which the
- * - * @exception IllegalArgumentException - * if repeatInterval is <= 0 - */ - public void setRepeatInterval(long repeatInterval) { - if (repeatInterval < 0) - throw new IllegalArgumentException( - "Repeat interval must be >= 0"); - - this.repeatInterval = repeatInterval; - } - - /** - *SimpleTrigger
- * should repeat. - *- * Get the number of times the
- */ - public int getTimesTriggered() { - return timesTriggered; - } - - /** - *SimpleTrigger
has already - * fired. - *- * Set the number of times the
- */ - public void setTimesTriggered(int timesTriggered) { - this.timesTriggered = timesTriggered; - } - - protected boolean validateMisfireInstruction(int misfireInstruction) { - if (misfireInstruction < MISFIRE_INSTRUCTION_SMART_POLICY) - return false; - - if (misfireInstruction > MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT) - return false; - - return true; - } - - /** - *SimpleTrigger
has already - * fired. - *- * Updates the
- * - *SimpleTrigger
's state based on the - * MISFIRE_INSTRUCTION_XXX that was selected when theSimpleTrigger
- * was created. - *- * If the misfire instruction is set to MISFIRE_INSTRUCTION_SMART_POLICY, - * then the following scheme will be used:
- *- *
- * - */ - public void updateAfterMisfire(Calendar cal) { - int instr = getMisfireInstruction(); - if (instr == Trigger.MISFIRE_INSTRUCTION_SMART_POLICY) { - if (getRepeatCount() == 0) instr = MISFIRE_INSTRUCTION_FIRE_NOW; - else if (getRepeatCount() == REPEAT_INDEFINITELY) instr = MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT; - else - // if (getRepeatCount() > 0) - instr = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT; - } else if (instr == MISFIRE_INSTRUCTION_FIRE_NOW - && getRepeatCount() != 0) - instr = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT; - - if (instr == MISFIRE_INSTRUCTION_FIRE_NOW) { - setNextFireTime(new Date()); - } else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT) { - Date newFireTime = getFireTimeAfter(new Date()); - while (newFireTime != null && cal != null - && !cal.isTimeIncluded(newFireTime.getTime())) { - newFireTime = getFireTimeAfter(newFireTime); - } - setNextFireTime(newFireTime); - } else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT) { - Date newFireTime = getFireTimeAfter(new Date()); - while (newFireTime != null && cal != null - && !cal.isTimeIncluded(newFireTime.getTime())) { - newFireTime = getFireTimeAfter(newFireTime); - } - if (newFireTime != null) { - int timesMissed = computeNumTimesFiredBetween(nextFireTime, - newFireTime); - setTimesTriggered(getTimesTriggered() + timesMissed); - } - - setNextFireTime(newFireTime); - } else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT) { - Date newFireTime = new Date(); - if (repeatCount != 0 && repeatCount != REPEAT_INDEFINITELY) { - setRepeatCount(getRepeatCount() - getTimesTriggered()); - setTimesTriggered(0); - } - setStartTime(newFireTime); - setNextFireTime(newFireTime); - } else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT) { - Date newFireTime = new Date(); - - int timesMissed = computeNumTimesFiredBetween(nextFireTime, - newFireTime); - - if (repeatCount != 0 && repeatCount != REPEAT_INDEFINITELY) { - int remainingCount = getRepeatCount() - - (getTimesTriggered() + timesMissed); - if (remainingCount <= 0) { - remainingCount = 0; - } - setRepeatCount(remainingCount); - setTimesTriggered(0); - } - - if(getEndTime() != null && getEndTime().before(newFireTime)) - setEndTime(new Date(newFireTime.getTime() + 50)); - - setStartTime(newFireTime); - setNextFireTime(newFireTime); - } - - } - - /** - *- If the Repeat Count is
- *0
, then the instruction will - * be interpreted asMISFIRE_INSTRUCTION_FIRE_NOW
.- If the Repeat Count is
- *REPEAT_INDEFINITELY
, then - * the instruction will be interpreted asMISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
. - * WARNING: using MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT - * with a trigger that has a non-null end-time may cause the trigger to - * never fire again if the end-time arrived during the misfire time span. - *- If the Repeat Count is
- *> 0
, then the instruction - * will be interpreted asMISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
. - *- * Called when the
- * - * @see #executionComplete(JobExecutionContext, JobExecutionException) - */ - public void triggered(Calendar calendar) { - timesTriggered++; - previousFireTime = nextFireTime; - nextFireTime = getFireTimeAfter(nextFireTime); - - while (nextFireTime != null && calendar != null - && !calendar.isTimeIncluded(nextFireTime.getTime())) { - nextFireTime = getFireTimeAfter(nextFireTime); - } - } - - /** - * - * @see org.quartz.Trigger#updateWithNewCalendar(org.quartz.Calendar, long) - */ - public void updateWithNewCalendar(Calendar calendar, long misfireThreshold) - { - nextFireTime = getFireTimeAfter(previousFireTime); - - Date now = new Date(); - do { - while (nextFireTime != null && calendar != null - && !calendar.isTimeIncluded(nextFireTime.getTime())) { - nextFireTime = getFireTimeAfter(nextFireTime); - } - - if(nextFireTime != null && nextFireTime.before(now)) { - long diff = now.getTime() - nextFireTime.getTime(); - if(diff >= misfireThreshold) { - nextFireTime = getFireTimeAfter(nextFireTime); - continue; - } - } - }while(false); - } - - /** - *{@link Scheduler}
has decided to 'fire' - * the trigger (execute the associatedJob
), in order to - * give theTrigger
a chance to update itself for its next - * triggering (if any). - *- * Called by the scheduler at the time a
- * - *Trigger
is first - * added to the scheduler, in order to have theTrigger
- * compute its first fire time, based on any associated calendar. - *- * After this method has been called,
- * - * @return the first time at which thegetNextFireTime()
- * should return a valid answer. - *Trigger
will be fired - * by the scheduler, which is also the same valuegetNextFireTime()
- * will return (until after the first firing of theTrigger
). - * - */ - public Date computeFirstFireTime(Calendar calendar) { - nextFireTime = getStartTime(); - - while (nextFireTime != null && calendar != null - && !calendar.isTimeIncluded(nextFireTime.getTime())) { - nextFireTime = getFireTimeAfter(nextFireTime); - } - - return nextFireTime; - } - - /** - *- * Called after the
- * - * @param context - * is the{@link Scheduler}
has executed the - *{@link org.quartz.JobDetail}
associated with theTrigger
- * in order to get the final instruction code from the trigger. - *JobExecutionContext
that was used by the - *Job
'sexecute(xx)
method. - * @param result - * is theJobExecutionException
thrown by the - *Job
, if any (may be null). - * @return one of the Trigger.INSTRUCTION_XXX constants. - * - * @see #INSTRUCTION_NOOP - * @see #INSTRUCTION_RE_EXECUTE_JOB - * @see #INSTRUCTION_DELETE_TRIGGER - * @see #INSTRUCTION_SET_TRIGGER_COMPLETE - * @see #triggered(Calendar) - */ - public int executionComplete(JobExecutionContext context, - JobExecutionException result) { - if (result != null && result.refireImmediately()) - return INSTRUCTION_RE_EXECUTE_JOB; - - if (result != null && result.unscheduleFiringTrigger()) - return INSTRUCTION_SET_TRIGGER_COMPLETE; - - if (result != null && result.unscheduleAllTriggers()) - return INSTRUCTION_SET_ALL_JOB_TRIGGERS_COMPLETE; - - if (!mayFireAgain()) return INSTRUCTION_DELETE_TRIGGER; - - return INSTRUCTION_NOOP; - } - - /** - *- * Returns the next time at which the
- */ - public Date getNextFireTime() { - return nextFireTime; - } - - /** - *SimpleTrigger
will - * fire. If the trigger will not fire again,null
will be - * returned. The value returned is not guaranteed to be valid until after - * theTrigger
has been added to the scheduler. - *- * Returns the previous time at which the
SimpleTrigger
will - * fire. If the trigger has not yet fired,null
will be - * returned. - */ - public Date getPreviousFireTime() { - return previousFireTime; - } - - /** - *- * Set the next time at which the
- * - *SimpleTrigger
should fire. - *- * This method should not be invoked by client code. - *
- */ - public void setNextFireTime(Date nextFireTime) { - this.nextFireTime = nextFireTime; - } - - /** - *- * Set the previous time at which the
- * - *SimpleTrigger
fired. - *- * This method should not be invoked by client code. - *
- */ - public void setPreviousFireTime(Date previousFireTime) { - this.previousFireTime = previousFireTime; - } - - /** - *- * Returns the next time at which the
- */ - public Date getFireTimeAfter(Date afterTime) { - if (complete) return null; - - if ((timesTriggered > repeatCount) - && (repeatCount != REPEAT_INDEFINITELY)) return null; - - if (afterTime == null) afterTime = new Date(); - - if (repeatCount == 0 && afterTime.compareTo(getStartTime()) >= 0) - return null; - - long startMillis = getStartTime().getTime(); - long afterMillis = afterTime.getTime(); - long endMillis = (getEndTime() == null) ? Long.MAX_VALUE : getEndTime() - .getTime(); - - if (endMillis <= afterMillis) return null; - - if (startMillis < afterMillis && repeatCount == 0) return null; - - if (afterMillis < startMillis) return new Date(startMillis); - - long numberoftimesexecutedplusone = ((afterMillis - startMillis) / repeatInterval) + 1; - - if ((numberoftimesexecutedplusone > repeatCount) - && (repeatCount != REPEAT_INDEFINITELY)) return null; - - Date time = new Date((numberoftimesexecutedplusone * repeatInterval) - + startMillis); - - if (endMillis <= time.getTime()) return null; - - return time; - } - - /** - *SimpleTrigger
will - * fire, after the given time. If the trigger will not fire after the given - * time,null
will be returned. - *- * Returns the last time at which the
- */ - public Date getFireTimeBefore(Date end) { - if (end.getTime() < getStartTime().getTime()) return null; - - int numFires = computeNumTimesFiredBetween(getStartTime(), end); - - return new Date(getStartTime().getTime() + (numFires * repeatInterval)); - } - - public int computeNumTimesFiredBetween(Date start, Date end) { - long time = end.getTime() - start.getTime(); - - return (int) (time / repeatInterval); - } - - /** - *SimpleTrigger
will - * fire, before the given time. If the trigger will not fire before the - * given time,null
will be returned. - *- * Returns the final time at which the
- * - *SimpleTrigger
will - * fire, if repeatCount is REPEAT_INDEFINITELY, null will be returned. - *- * Note that the return time may be in the past. - *
- */ - public Date getFinalFireTime() { - if (repeatCount == 0) return startTime; - - if (repeatCount == REPEAT_INDEFINITELY && getEndTime() == null) - return null; - - if (repeatCount == REPEAT_INDEFINITELY && getEndTime() == null) return null; - else if (repeatCount == REPEAT_INDEFINITELY) - return getFireTimeBefore(getEndTime()); - - long lastTrigger = startTime.getTime() + (repeatCount * repeatInterval); - - if ((getEndTime() == null) || (lastTrigger < getEndTime().getTime())) return new Date( - lastTrigger); - else - return getFireTimeBefore(getEndTime()); - } - - /** - *- * Determines whether or not the
- */ - public boolean mayFireAgain() { - return (getNextFireTime() != null); - } - - /** - *SimpleTrigger
will occur - * again. - *- * Validates whether the properties of the
- */ - public abstract Date computeFirstFireTime(Calendar calendar); - - /** - *JobDetail
are - * valid for submission into aScheduler
. - * - * @throws IllegalStateException - * if a required property (such as Name, Group, Class) is not - * set. - */ - public void validate() throws SchedulerException { - super.validate(); - - if (repeatCount != 0 && repeatInterval < 1) - throw new SchedulerException("Repeat Interval cannot be zero.", - SchedulerException.ERR_CLIENT_ERROR); - } - - public static void main(String[] args) // TODO: remove method after good - // unit testing - throws Exception { - - Date sdt = new Date(); - - Date edt = new Date(sdt.getTime() + 55000L); - - SimpleTrigger st = new SimpleTrigger("t", "g", "j", "g", sdt, edt, 10, - 10000L); - - System.err.println(); - - st.computeFirstFireTime(null); - - System.err.println("lastTime=" + st.getFinalFireTime()); - - java.util.List times = TriggerUtils.computeFireTimes(st, null, 50); - - for (int i = 0; i < times.size(); i++) { - System.err.println("firetime = " + times.get(i)); - } - } - + TriggerBuildergetTriggerBuilder(); } Index: 3rdParty_sources/quartz/org/quartz/StatefulJob.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/StatefulJob.java (.../StatefulJob.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/StatefulJob.java (.../StatefulJob.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,16 +16,11 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; /** - * * A marker interface for
* *{@link org.quartz.JobDetail}
s that * wish to have their state maintained between executions. - **
* + * @see DisallowConcurrentExecution + * @see PersistJobDataAfterExecution + * * @see Job * @see JobDetail * @see JobDataMap * @see Scheduler * + * + * @deprecated use DisallowConcurrentExecution and/or PersistJobDataAfterExecution annotations instead. + * * @author James House */ +@PersistJobDataAfterExecution +@DisallowConcurrentExecution public interface StatefulJob extends Job { /* Index: 3rdParty_sources/quartz/org/quartz/TimeOfDay.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/TimeOfDay.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/TimeOfDay.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,243 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +package org.quartz; + +import java.io.Serializable; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +/** + * Represents a time in hour, minute and second of any given day. + * + *StatefulJob
instances follow slightly different rules from @@ -37,13 +32,21 @@ * theexecute(xx)
method will be delayed. *The hour is in 24-hour convention, meaning values are from 0 to 23.
+ * + * @see DailyTimeIntervalScheduleBuilder + * + * @since 2.0.3 + * + * @author James House + * @author Zemian Deng+ */ +public class TimeOfDay implements Serializable { + + private static final long serialVersionUID = 2964774315889061771L; + + private final int hour; + private final int minute; + private final int second; + + /** + * Create a TimeOfDay instance for the given hour, minute and second. + * + * @param hour The hour of day, between 0 and 23. + * @param minute The minute of the hour, between 0 and 59. + * @param second The second of the minute, between 0 and 59. + * @throws IllegalArgumentException if one or more of the input values is out of their valid range. + */ + public TimeOfDay(int hour, int minute, int second) { + this.hour = hour; + this.minute = minute; + this.second = second; + validate(); + } + + /** + * Create a TimeOfDay instance for the given hour and minute (at the zero second of the minute). + * + * @param hour The hour of day, between 0 and 23. + * @param minute The minute of the hour, between 0 and 59. + * @throws IllegalArgumentException if one or more of the input values is out of their valid range. + */ + public TimeOfDay(int hour, int minute) { + this.hour = hour; + this.minute = minute; + this.second = 0; + validate(); + } + + private void validate() { + if(hour < 0 || hour > 23) + throw new IllegalArgumentException("Hour must be from 0 to 23"); + if(minute < 0 || minute > 59) + throw new IllegalArgumentException("Minute must be from 0 to 59"); + if(second < 0 || second > 59) + throw new IllegalArgumentException("Second must be from 0 to 59"); + } + + /** + * Create a TimeOfDay instance for the given hour, minute and second. + * + * @param hour The hour of day, between 0 and 23. + * @param minute The minute of the hour, between 0 and 59. + * @param second The second of the minute, between 0 and 59. + * @throws IllegalArgumentException if one or more of the input values is out of their valid range. + */ + public static TimeOfDay hourMinuteAndSecondOfDay(int hour, int minute, int second) { + return new TimeOfDay(hour, minute, second); + } + + /** + * Create a TimeOfDay instance for the given hour and minute (at the zero second of the minute). + * + * @param hour The hour of day, between 0 and 23. + * @param minute The minute of the hour, between 0 and 59. + * @throws IllegalArgumentException if one or more of the input values is out of their valid range. + */ + public static TimeOfDay hourAndMinuteOfDay(int hour, int minute) { + return new TimeOfDay(hour, minute); + } + + /** + * The hour of the day (between 0 and 23). + * + * @return The hour of the day (between 0 and 23). + */ + public int getHour() { + return hour; + } + + /** + * The minute of the hour. + * + * @return The minute of the hour (between 0 and 59). + */ + public int getMinute() { + return minute; + } + + /** + * The second of the minute. + * + * @return The second of the minute (between 0 and 59). + */ + public int getSecond() { + return second; + } + + /** + * Determine with this time of day is before the given time of day. + * + * @return true this time of day is before the given time of day. + */ + public boolean before(TimeOfDay timeOfDay) { + + if(timeOfDay.hour > hour) + return true; + if(timeOfDay.hour < hour) + return false; + + if(timeOfDay.minute > minute) + return true; + if(timeOfDay.minute < minute) + return false; + + if(timeOfDay.second > second) + return true; + if(timeOfDay.second < second) + return false; + + return false; // must be equal... + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof TimeOfDay)) + return false; + + TimeOfDay other = (TimeOfDay)obj; + + return (other.hour == hour && other.minute == minute && other.second == second); + } + + @Override + public int hashCode() { + return (hour + 1) ^ (minute + 1) ^ (second + 1); + } + + /** Return a date with time of day reset to this object values. The millisecond value will be zero. */ + public Date getTimeOfDayForDate(Date dateTime) { + if (dateTime == null) + return null; + Calendar cal = Calendar.getInstance(); + cal.setTime(dateTime); + cal.set(Calendar.HOUR_OF_DAY, hour); + cal.set(Calendar.MINUTE, minute); + cal.set(Calendar.SECOND, second); + cal.clear(Calendar.MILLISECOND); + return cal.getTime(); + } + + /** + * Create a TimeOfDay from the given date, in the system default TimeZone. + * + * @param dateTime The java.util.Date from which to extract Hour, Minute and Second. + */ + public static TimeOfDay hourAndMinuteAndSecondFromDate(Date dateTime) { + return hourAndMinuteAndSecondFromDate(dateTime, null); + } + + /** + * Create a TimeOfDay from the given date, in the given TimeZone. + * + * @param dateTime The java.util.Date from which to extract Hour, Minute and Second. + * @param tz The TimeZone from which relate Hour, Minute and Second for the given date. If null, system default + * TimeZone will be used. + */ + public static TimeOfDay hourAndMinuteAndSecondFromDate(Date dateTime, TimeZone tz) { + if (dateTime == null) + return null; + Calendar cal = Calendar.getInstance(); + cal.setTime(dateTime); + if(tz != null) + cal.setTimeZone(tz); + + return new TimeOfDay(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND)); + } + + /** + * Create a TimeOfDay from the given date (at the zero-second), in the system default TimeZone. + * + * @param dateTime The java.util.Date from which to extract Hour and Minute. + */ + public static TimeOfDay hourAndMinuteFromDate(Date dateTime) { + return hourAndMinuteFromDate(dateTime, null); + } + + /** + * Create a TimeOfDay from the given date (at the zero-second), in the system default TimeZone. + * + * @param dateTime The java.util.Date from which to extract Hour and Minute. + * @param tz The TimeZone from which relate Hour and Minute for the given date. If null, system default + * TimeZone will be used. + */ + public static TimeOfDay hourAndMinuteFromDate(Date dateTime, TimeZone tz) { + if (dateTime == null) + return null; + Calendar cal = Calendar.getInstance(); + cal.setTime(dateTime); + if(tz != null) + cal.setTimeZone(tz); + + return new TimeOfDay(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)); + } + + @Override + public String toString() { + return "TimeOfDay[" + hour + ":" + minute + ":" + second + "]"; + } +} Index: 3rdParty_sources/quartz/org/quartz/Trigger.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/Trigger.java (.../Trigger.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/Trigger.java (.../Trigger.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,126 +16,85 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; +import java.io.Serializable; +import java.util.Comparator; import java.util.Date; -import java.util.LinkedList; + /** - * - * The base abstract class to be extended by all
+ * The base interface with properties common to allTrigger
s. - *Trigger
s - + * use {@link TriggerBuilder} to instantiate an actual Trigger. * *- *
* *Triggers
s have a name and group associated with them, which + *Triggers
s have a {@link TriggerKey} associated with them, which * should uniquely identify them within a single{@link Scheduler}
. *- *
* *Trigger
s are the 'mechanism' by whichJob
s - * are scheduled. ManyTrigger
s can point to the sameJob
, + *Trigger
s are the 'mechanism' by whichJob
s + * are scheduled. ManyTrigger
s can point to the sameJob
, * but a singleTrigger
can only point to oneJob
. ** Triggers can 'send' parameters/data to
- * - * @see SimpleTrigger - * @see CronTrigger - * @see NthIncludedDayTrigger - * @see TriggerUtils + * + * @see TriggerBuilder * @see JobDataMap * @see JobExecutionContext + * @see TriggerUtils + * @see SimpleTrigger + * @see CronTrigger + * @see CalendarIntervalTrigger * * @author James House - * @author Sharada Jambula */ -public abstract class Trigger implements java.io.Serializable, Cloneable, - Comparable { +public interface Trigger extends Serializable, Cloneable, ComparableJob
s by placing contents * into theJobDataMap
on theTrigger
. *{ - private static final long serialVersionUID = -3904243490805975570L; + public static final long serialVersionUID = -3904243490805975570L; - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + public enum TriggerState { NONE, NORMAL, PAUSED, COMPLETE, ERROR, BLOCKED } + + /** + * * - * Constants. + *
NOOP
Instructs the{@link Scheduler}
that the + *{@link Trigger}
has no further instructions.* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + *
RE_EXECUTE_JOB
Instructs the{@link Scheduler}
that the + *{@link Trigger}
wants the{@link org.quartz.JobDetail}
to + * re-execute immediately. If not in a 'RECOVERING' or 'FAILED_OVER' situation, the + * execution context will be re-used (giving theJob
the + * ability to 'see' anything placed in the context by its last execution).+ * + *
SET_TRIGGER_COMPLETE
Instructs the{@link Scheduler}
that the + *{@link Trigger}
should be put in theCOMPLETE
state.+ * + *
DELETE_TRIGGER
Instructs the{@link Scheduler}
that the + *{@link Trigger}
wants itself deleted.+ * + *
SET_ALL_JOB_TRIGGERS_COMPLETE
Instructs the{@link Scheduler}
+ * that allTrigger
s referencing the same{@link org.quartz.JobDetail}
+ * as this one should be put in theCOMPLETE
state.+ * + *
SET_TRIGGER_ERROR
Instructs the{@link Scheduler}
that all + *Trigger
s referencing the same{@link org.quartz.JobDetail}
as + * this one should be put in theERROR
state.*/ + public enum CompletedExecutionInstruction { NOOP, RE_EXECUTE_JOB, SET_TRIGGER_COMPLETE, DELETE_TRIGGER, + SET_ALL_JOB_TRIGGERS_COMPLETE, SET_TRIGGER_ERROR, SET_ALL_JOB_TRIGGERS_ERROR } /** - *
SET_ALL_JOB_TRIGGERS_ERROR
Instructs the{@link Scheduler}
that + * theTrigger
should be put in theERROR
state.- * Instructs the
- */ - public static final int INSTRUCTION_NOOP = 0; - - /** - *{@link Scheduler}
that the{@link Trigger}
- * has no further instructions. - *- * Instructs the
- */ - public static final int INSTRUCTION_RE_EXECUTE_JOB = 1; - - /** - *{@link Scheduler}
that the{@link Trigger}
- * wants the{@link org.quartz.JobDetail}
to re-execute - * immediately. If not in a 'RECOVERING' or 'FAILED_OVER' situation, the - * execution context will be re-used (giving theJob
the - * abilitiy to 'see' anything placed in the context by its last execution). - *- * Instructs the
- */ - public static final int INSTRUCTION_SET_TRIGGER_COMPLETE = 2; - - /** - *{@link Scheduler}
that the{@link Trigger}
- * should be put in theCOMPLETE
state. - *- * Instructs the
- */ - public static final int INSTRUCTION_DELETE_TRIGGER = 3; - - /** - *{@link Scheduler}
that the{@link Trigger}
- * wants itself deleted. - *- * Instructs the
- */ - public static final int INSTRUCTION_SET_ALL_JOB_TRIGGERS_COMPLETE = 4; - - /** - *{@link Scheduler}
that allTrigger
- * s referencing the same{@link org.quartz.JobDetail}
as - * this one should be put in theCOMPLETE
state. - *- * Instructs the
- */ - public static final int INSTRUCTION_SET_TRIGGER_ERROR = 5; - - /** - *{@link Scheduler}
that allTrigger
- * s referencing the same{@link org.quartz.JobDetail}
as - * this one should be put in theERROR
state. - *- * Instructs the
- */ - public static final int INSTRUCTION_SET_ALL_JOB_TRIGGERS_ERROR = 6; - - /** - *{@link Scheduler}
that theTrigger
- * should be put in theERROR
state. - ** Instructs the
+ * on the{@link Scheduler}
that upon a mis-fire * situation, theupdateAfterMisfire()
method will be called - * on theTrigger
to determine the mis-fire instruction. - *Trigger
to determine the mis-fire instruction, + * which logic will be trigger-implementation-dependent. * ** In order to see if this instruction fits your needs, you should look at @@ -144,788 +103,227 @@ *
*/ public static final int MISFIRE_INSTRUCTION_SMART_POLICY = 0; - + /** - *- * Indicates that the
- */ - public final static int STATE_NORMAL = 0; - - /** - *Trigger
is in the "normal" state. - *- * Indicates that the
- */ - public final static int STATE_PAUSED = 1; - - /** - *Trigger
is in the "paused" state. - *- * Indicates that the
+ * Instructs theTrigger
is in the "complete" state. - *{@link Scheduler}
that the + *Trigger
will never be evaluated for a misfire situation, + * and that the scheduler will simply try to fire it as soon as it can, + * and then update the Trigger as if it had fired at the proper time. * - *- * "Complete" indicates that the trigger has not remaining fire-times in - * its schedule. - *
+ *NOTE: if a trigger uses this instruction, and it has missed + * several of its scheduled firings, then several rapid firings may occur + * as the trigger attempt to catch back up to where it would have been. + * For example, a SimpleTrigger that fires every 15 seconds which has + * misfired for 5 minutes will fire 20 times once it gets the chance to + * fire.
*/ - public final static int STATE_COMPLETE = 2; - + public static final int MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY = -1; + /** - *- * Indicates that the
- * - *Trigger
is in the "error" state. - *- * A
- * - *Trigger
arrives at the error state when the scheduler - * attempts to fire it, but cannot due to an error creating and executing - * its related job. Often this is due to theJob
's - * class not existing in the classpath. - *- * When the trigger is in the error state, the scheduler will make no - * attempts to fire it. - *
+ * The default value for priority. */ - public final static int STATE_ERROR = 3; + public static final int DEFAULT_PRIORITY = 5; + public TriggerKey getKey(); - /** - *- * Indicates that the
- * - *Trigger
is in the "blocked" state. - *- * A
- * - * @see StatefulJob - */ - public final static int STATE_BLOCKED = 4; - - /** - *Trigger
arrives at the blocked state when the job that - * it is associated with is aStatefulJob
and it is - * currently executing. - *- * Indicates that the
- */ - public final static int STATE_NONE = -1; - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Data members. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - - private String name; - - private String group = Scheduler.DEFAULT_GROUP; - - private String jobName; - - private String jobGroup = Scheduler.DEFAULT_GROUP; - - private String description; + public JobKey getJobKey(); - private JobDataMap jobDataMap; - - private boolean volatility = false; - - private String calendarName = null; - - private String fireInstanceId = null; - - private int misfireInstruction = MISFIRE_INSTRUCTION_SMART_POLICY; - - private LinkedList triggerListeners = new LinkedList(); - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Constructors. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - /** - *Trigger
does not exist. - *- * Create a
- * - *Trigger
with no specified name, group, or{@link org.quartz.JobDetail}
. - *- * Note that the {@link #setName(String)},{@link #setGroup(String)}and - * the {@link #setJobName(String)}and {@link #setJobGroup(String)}methods - * must be called before the
- */ - public Trigger() { - // do nothing... - } - - /** - *Trigger
can be placed into a - * {@link Scheduler}. - *- * Create a
- * - *Trigger
with the given name, and group. - *- * Note that the {@link #setJobName(String)}and - * {@link #setJobGroup(String)}methods must be called before the
- * - * @param group ifTrigger
- * can be placed into a {@link Scheduler}. - *null
, Scheduler.DEFAULT_GROUP will be used. - * - * @exception IllegalArgumentException - * if name is null or empty, or the group is an empty string. - */ - public Trigger(String name, String group) { - setName(name); - setGroup(group); - } - - /** - *- * Create a
- * - * @param group ifTrigger
with the given name, and group. - *null
, Scheduler.DEFAULT_GROUP will be used. - * - * @exception IllegalArgumentException - * if name is null or empty, or the group is an empty string. - */ - public Trigger(String name, String group, String jobName, String jobGroup) { - setName(name); - setGroup(group); - setJobName(jobName); - setJobGroup(jobGroup); - } - - /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Interface. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - - /** - *- * Get the name of this
- */ - public String getName() { - return name; - } - - /** - *Trigger
. - *- * Set the name of this
- * - * @exception IllegalArgumentException - * if name is null or empty. - */ - public void setName(String name) { - if (name == null || name.trim().length() == 0) - throw new IllegalArgumentException( - "Trigger name cannot be null or empty."); - - this.name = name; - } - - /** - *Trigger
. - *- * Get the group of this
- */ - public String getGroup() { - return group; - } - - /** - *Trigger
. - *- * Set the name of this
- * - * @param group ifTrigger
. - *null
, Scheduler.DEFAULT_GROUP will be used. - * - * @exception IllegalArgumentException - * if group is an empty string. - */ - public void setGroup(String group) { - if (group != null && group.trim().length() == 0) - throw new IllegalArgumentException( - "Group name cannot be an empty string."); - - if(group == null) - group = Scheduler.DEFAULT_GROUP; - - this.group = group; - } - - /** - *- * Get the name of the associated
- */ - public String getJobName() { - return jobName; - } - - /** - *{@link org.quartz.JobDetail}
. - *- * Set the name of the associated
- * - * @exception IllegalArgumentException - * if jobName is null or empty. - */ - public void setJobName(String jobName) { - if (jobName == null || jobName.trim().length() == 0) - throw new IllegalArgumentException( - "Job name cannot be null or empty."); - - this.jobName = jobName; - } - - /** - *{@link org.quartz.JobDetail}
. - *- * Get the name of the associated
- */ - public String getJobGroup() { - return jobGroup; - } - - /** - *{@link org.quartz.JobDetail}
's - * group. - *- * Set the name of the associated
- * - * @param group if{@link org.quartz.JobDetail}
's - * group. - *null
, Scheduler.DEFAULT_GROUP will be used. - * - * @exception IllegalArgumentException - * if group is an empty string. - */ - public void setJobGroup(String jobGroup) { - if (jobGroup != null && jobGroup.trim().length() == 0) - throw new IllegalArgumentException( - "Group name cannot be null or empty."); - - if(jobGroup == null) - jobGroup = Scheduler.DEFAULT_GROUP; - - this.jobGroup = jobGroup; - } - - /** - *- * Returns the 'full name' of the
- */ - public String getFullName() { - return group + "." + name; - } - - /** - *Trigger
in the format - * "group.name". - *- * Returns the 'full name' of the
- */ - public String getFullJobName() { - return jobGroup + "." + jobName; - } - - /** - *Job
that theTrigger
- * points to, in the format "group.name". - ** Return the description given to the
* * @return null if no description was set. */ - public String getDescription() { - return description; - } + public String getDescription(); /** - *Trigger
instance by * its creator (if any). - *- * Set a description for the
- */ - public void setDescription(String description) { - this.description = description; - } - - /** - *Trigger
instance - may be - * useful for remembering/displaying the purpose of the trigger, though the - * description has no meaning to Quartz. - *- * Set whether or not the
- */ - public void setVolatility(boolean volatility) { - this.volatility = volatility; - } - - /** - *Trigger
should be persisted in the - *{@link org.quartz.spi.JobStore}
for re-use after program - * restarts. - *- * Associate the
- * - * @param calendarName - * use{@link Calendar}
with the given name with - * this Trigger. - *null
to dis-associate a Calendar. - */ - public void setCalendarName(String calendarName) { - this.calendarName = calendarName; - } - - /** - ** Get the name of the
* * @return{@link Calendar}
associated with this * Trigger. - *null
if there is no associated Calendar. */ - public String getCalendarName() { - return calendarName; - } + public String getCalendarName(); /** - ** Get the
* *JobDataMap
that is associated with the *Trigger
. - ** Changes made to this map during job execution are not re-persisted, and * in fact typically result in an
*/ - public JobDataMap getJobDataMap() { - if (jobDataMap == null) jobDataMap = new JobDataMap(); - return jobDataMap; - } + public JobDataMap getJobDataMap(); - /** - *IllegalStateException
. *- * Set the
- */ - public void setJobDataMap(JobDataMap jobDataMap) { - this.jobDataMap = jobDataMap; - } - - /** - *JobDataMap
to be associated with the - *Trigger
. - *- * Whether or not the
+ * The priority of aTrigger
should be persisted in the - *{@link org.quartz.spi.JobStore}
for re-use after program - * restarts. - *Trigger
acts as a tiebreaker such that if + * twoTrigger
s have the same scheduled fire time, then the + * one with the higher priority will get first access to a worker + * thread. * *- * If not explicitly set, the default value is
* - * @returnfalse
. + * If not explicitly set, the default value is5
. *true
if theTrigger
should be - * garbage collected along with the{@link Scheduler}
. + * @see #DEFAULT_PRIORITY */ - public boolean isVolatile() { - return volatility; - } + public int getPriority(); /** - *- * Add the specified name of a
- */ - public void addTriggerListener(String name) { - triggerListeners.add(name); - } - - /** - *{@link TriggerListener}
to - * the end of theTrigger
's list of listeners. - *- * Remove the specified name of a
- * - * @return true if the given name was found in the list, and removed - */ - public boolean removeTriggerListener(String name) { - return triggerListeners.remove(name); - } - - /** - *{@link TriggerListener}
- * from theTrigger
's list of listeners. - *- * Returns an array of
- */ - public String[] getTriggerListenerNames() { - String[] outNames = new String[triggerListeners.size()]; - return (String[]) triggerListeners.toArray(outNames); - } - - /** - *String
s containing the names of all - *{@link TriggerListener}
assigned to theTrigger
, - * in the order in which they should be notified. - *- * This method should not be used by the Quartz client. - *
- * - *- * Called when the
- * - * @see #executionComplete(JobExecutionContext, JobExecutionException) - */ - public abstract void triggered(Calendar calendar); - - /** - *{@link Scheduler}
has decided to 'fire' - * the trigger (execute the associatedJob
), in order to - * give theTrigger
a chance to update itself for its next - * triggering (if any). - *- * This method should not be used by the Quartz client. - *
- * - *- * Called by the scheduler at the time a
- * - *Trigger
is first - * added to the scheduler, in order to have theTrigger
- * compute its first fire time, based on any associated calendar. - *- * After this method has been called,
- * - * @return the first time at which thegetNextFireTime()
- * should return a valid answer. - *Trigger
will be fired - * by the scheduler, which is also the same valuegetNextFireTime()
- * will return (until after the first firing of theTrigger
). - *- * This method should not be used by the Quartz client. - *
- * - *- * Called after the
- * - * @param context - * is the{@link Scheduler}
has executed the - *{@link org.quartz.JobDetail}
associated with theTrigger
- * in order to get the final instruction code from the trigger. - *JobExecutionContext
that was used by the - *Job
'sexecute(xx)
method. - * @param result - * is theJobExecutionException
thrown by the - *Job
, if any (may be null). - * @return one of the Trigger.INSTRUCTION_XXX constants. - * - * @see #INSTRUCTION_NOOP - * @see #INSTRUCTION_RE_EXECUTE_JOB - * @see #INSTRUCTION_DELETE_TRIGGER - * @see #INSTRUCTION_SET_TRIGGER_COMPLETE - * @see #triggered(Calendar) - */ - public abstract int executionComplete(JobExecutionContext context, - JobExecutionException result); - - /** - ** Used by the
* *{@link Scheduler}
to determine whether or not * it is possible for thisTrigger
to fire again. - ** If the returned value is
*/ - public abstract boolean mayFireAgain(); + public boolean mayFireAgain(); /** - *false
then theScheduler
* may remove theTrigger
from the{@link org.quartz.spi.JobStore}
. ** Get the time at which the
*/ - public abstract Date getStartTime(); + public Date getStartTime(); - public abstract void setStartTime(Date startTime); - - public abstract void setEndTime(Date endTime); - /** - *Trigger
should occur. - ** Get the time at which the
+ * regardless of any remaining repeats (based on the trigger's particular + * repeat settings). * * @see #getFinalFireTime() */ - public abstract Date getEndTime(); + public Date getEndTime(); /** - *Trigger
should quit repeating - - * even if an assigned 'repeatCount' isn't yet satisfied. - *- * Returns the next time at which the
Trigger
will fire. If - * the trigger will not fire again,null
will be returned. - * The value returned is not guaranteed to be valid until after theTrigger
+ * Returns the next time at which theTrigger
is scheduled to fire. If + * the trigger will not fire again,null
will be returned. Note that + * the time returned can possibly be in the past, if the time that was computed + * for the trigger to next fire has already arrived, but the scheduler has not yet + * been able to fire the trigger (which would likely be due to lack of resources + * e.g. threads). + * + *The value returned is not guaranteed to be valid until after the
+ * + * @see TriggerUtils#computeFireTimesBetween(org.quartz.spi.OperableTrigger, Calendar, java.util.Date, java.util.Date) */ - public abstract Date getNextFireTime(); + public Date getNextFireTime(); /** - *Trigger
* has been added to the scheduler. *- * Returns the previous time at which the
Trigger
will fire. + * Returns the previous time at which theTrigger
fired. * If the trigger has not yet fired,null
will be returned. */ - public abstract Date getPreviousFireTime(); + public Date getPreviousFireTime(); /** - ** Returns the next time at which the
*/ - public abstract Date getFireTimeAfter(Date afterTime); + public Date getFireTimeAfter(Date afterTime); /** - *Trigger
will fire, * after the given time. If the trigger will not fire after the given time, *null
will be returned. - ** Returns the last time at which the
* *Trigger
will fire, if * the Trigger will repeat indefinitely, null will be returned. - ** Note that the return time *may* be in the past. *
*/ - public abstract Date getFinalFireTime(); + public Date getFinalFireTime(); /** - *- * Set the instruction the
- * - *Scheduler
should be given for - * handling misfire situations for thisTrigger
- the - * concreteTrigger
type that you are using will have - * defined a set of additionalMISFIRE_INSTRUCTION_XXX
- * constants that may be passed to this method. - *- * If not explicitly set, the default value is
- * - * @see #MISFIRE_INSTRUCTION_SMART_POLICY - * @see #updateAfterMisfire(Calendar) - * @see SimpleTrigger - * @see CronTrigger - */ - public void setMisfireInstruction(int misfireInstruction) { - if (!validateMisfireInstruction(misfireInstruction)) - throw new IllegalArgumentException( - "The misfire instruction code is invalid for this type of trigger."); - this.misfireInstruction = misfireInstruction; - } - - protected abstract boolean validateMisfireInstruction(int misfireInstruction); - - /** - *MISFIRE_INSTRUCTION_SMART_POLICY
. - ** Get the instruction the
+ * constants that may be set as this property's value. * *Scheduler
should be given for * handling misfire situations for thisTrigger
- the * concreteTrigger
type that you are using will have * defined a set of additionalMISFIRE_INSTRUCTION_XXX
- * constants that may be passed to this method. - ** If not explicitly set, the default value is
* * @see #MISFIRE_INSTRUCTION_SMART_POLICY - * @see #updateAfterMisfire(Calendar) * @see SimpleTrigger * @see CronTrigger */ - public int getMisfireInstruction() { - return misfireInstruction; - } + public int getMisfireInstruction(); /** - *MISFIRE_INSTRUCTION_SMART_POLICY
. *- * This method should not be used by the Quartz client. - *
+ * Get a {@link TriggerBuilder} that is configured to produce a + *Trigger
identical to this one. * - *- * To be implemented by the concrete classes that extend this class. - *
- * - *- * The implementation should update the
+ * @see #getScheduleBuilder() */ - public abstract void updateAfterMisfire(Calendar cal); - + public TriggerBuilder extends Trigger> getTriggerBuilder(); + /** - *Trigger
's state - * based on the MISFIRE_INSTRUCTION_XXX that was selected when theTrigger
- * was created. - *- * This method should not be used by the Quartz client. - *
+ * Get a {@link ScheduleBuilder} that is configured to produce a + * schedule identical to this trigger's schedule. * - *- * To be implemented by the concrete class. - *
- * - *- * The implementation should update the
- * - * @param cal + * @see #getTriggerBuilder() */ - public abstract void updateWithNewCalendar(Calendar cal, long misfireThreshold); + public ScheduleBuilder extends Trigger> getScheduleBuilder(); /** - *Trigger
's state - * based on the given new version of the associatedCalendar
- * (the state should be updated so that it's next fire time is appropriate - * given the Calendar's new settings). - *- * Validates whether the properties of the
JobDetail
are - * valid for submission into aScheduler
. + * Trigger equality is based upon the equality of the TriggerKey. * - * @throws IllegalStateException - * if a required property (such as Name, Group, Class) is not - * set. + * @return true if the key of this Trigger equals that of the given Trigger. */ - public void validate() throws SchedulerException { - if (name == null) - throw new SchedulerException("Trigger's name cannot be null", - SchedulerException.ERR_CLIENT_ERROR); - - if (group == null) - throw new SchedulerException("Trigger's group cannot be null", - SchedulerException.ERR_CLIENT_ERROR); - - if (jobName == null) - throw new SchedulerException( - "Trigger's related Job's name cannot be null", - SchedulerException.ERR_CLIENT_ERROR); - - if (jobGroup == null) - throw new SchedulerException( - "Trigger's related Job's group cannot be null", - SchedulerException.ERR_CLIENT_ERROR); - } - + public boolean equals(Object other); + /** *- * This method should not be used by the Quartz client. + * Compare the next fire time of this
- * - *Trigger
to that of + * another by comparing their keys, or in other words, sorts them + * according to the natural (i.e. alphabetical) order of their keys. *- * Usable by
- * - * */ - public void setFireInstanceId(String id) { - this.fireInstanceId = id; - } + public int compareTo(Trigger other); /** - *{@link org.quartz.spi.JobStore}
- * implementations, in order to facilitate 'recognizing' instances of fired - *Trigger
s as their jobs complete execution. - *- * This method should not be used by the Quartz client. - *
+ * A Comparator that compares trigger's next fire times, or in other words, + * sorts them according to earliest next fire time. If the fire times are + * the same, then the triggers are sorted according to priority (highest + * value first), if the priorities are the same, then they are sorted + * by key. */ - public String getFireInstanceId() { - return fireInstanceId; - } + class TriggerTimeComparator implements Comparator, Serializable { + + private static final long serialVersionUID = -3904243490805975570L; + + // This static method exists for comparator in TC clustered quartz + public static int compare(Date nextFireTime1, int priority1, TriggerKey key1, Date nextFireTime2, int priority2, TriggerKey key2) { + if (nextFireTime1 != null || nextFireTime2 != null) { + if (nextFireTime1 == null) { + return 1; + } - /** - * - * Return a simple string representation of this object. - *
- */ - public String toString() { - return "Trigger '" + getFullName() + "': triggerClass: '" - + getClass().getName() + " isVolatile: " + isVolatile() - + " calendar: '" + getCalendarName() + "' misfireInstruction: " - + getMisfireInstruction() + " nextFireTime: " + getNextFireTime(); - } + if (nextFireTime2 == null) { + return -1; + } - /** - *- * Compare the next fire time of this
- */ - public int compareTo(Object obj) { - Trigger other = (Trigger) obj; + if(nextFireTime1.before(nextFireTime2)) { + return -1; + } - Date myTime = getNextFireTime(); - Date otherTime = other.getNextFireTime(); + if(nextFireTime1.after(nextFireTime2)) { + return 1; + } + } - if (myTime == null && otherTime == null) return 0; + int comp = priority2 - priority1; + if (comp != 0) { + return comp; + } - if (myTime == null) return 1; + return key1.compareTo(key2); + } - if (otherTime == null) return -1; - if(myTime.before(otherTime)) - return -1; - - if(myTime.after(otherTime)) - return 1; - - return 0; - } - - public boolean equals(Object obj) { - if (!(obj instanceof Trigger)) return false; - - Trigger other = (Trigger) obj; - - if (!other.getName().equals(getName())) return false; - if (!other.getGroup().equals(getGroup())) return false; - - return true; - } - - - public int hashCode() { - return getFullName().hashCode(); - } - - public Object clone() { - Trigger copy; - try { - copy = (Trigger) super.clone(); - } catch (CloneNotSupportedException ex) { - throw new IncompatibleClassChangeError("Not Cloneable."); + public int compare(Trigger t1, Trigger t2) { + return compare(t1.getNextFireTime(), t1.getPriority(), t1.getKey(), t2.getNextFireTime(), t2.getPriority(), t2.getKey()); } - return copy; } - } Index: 3rdParty_sources/quartz/org/quartz/TriggerBuilder.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/TriggerBuilder.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/TriggerBuilder.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,416 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import java.util.Date; + +import org.quartz.spi.MutableTrigger; +import org.quartz.utils.Key; + +/** + *Trigger
to that of - * another. - *TriggerBuilder
is used to instantiate {@link Trigger}s. + * + *The builder will always try to keep itself in a valid state, with + * reasonable defaults set for calling build() at any point. For instance + * if you do not invoke withSchedule(..) method, a default schedule + * of firing once immediately will be used. As another example, if you + * do not invoked withIdentity(..) a trigger name will be generated + * for you.
+ * + *Quartz provides a builder-style API for constructing scheduling-related + * entities via a Domain-Specific Language (DSL). The DSL can best be + * utilized through the usage of static imports of the methods on the classes + *
+ * + *TriggerBuilder
,JobBuilder
, + *DateBuilder
,JobKey
,TriggerKey
+ * and the variousScheduleBuilder
implementations.Client code can then use the DSL to write code such as this:
+ *+ * JobDetail job = newJob(MyJob.class) + * .withIdentity("myJob") + * .build(); + * + * Trigger trigger = newTrigger() + * .withIdentity(triggerKey("myTrigger", "myTriggerGroup")) + * .withSchedule(simpleSchedule() + * .withIntervalInHours(1) + * .repeatForever()) + * .startAt(futureDate(10, MINUTES)) + * .build(); + * + * scheduler.scheduleJob(job, trigger); + *+ * + * @see JobBuilder + * @see ScheduleBuilder + * @see DateBuilder + * @see Trigger + */ +public class TriggerBuilder{ + + private TriggerKey key; + private String description; + private Date startTime = new Date(); + private Date endTime; + private int priority = Trigger.DEFAULT_PRIORITY; + private String calendarName; + private JobKey jobKey; + private JobDataMap jobDataMap = new JobDataMap(); + + private ScheduleBuilder> scheduleBuilder = null; + + private TriggerBuilder() { + + } + + /** + * Create a new TriggerBuilder with which to define a + * specification for a Trigger. + * + * @return the new TriggerBuilder + */ + public static TriggerBuilder newTrigger() { + return new TriggerBuilder (); + } + + /** + * Produce the Trigger
. + * + * @return a Trigger that meets the specifications of the builder. + */ + @SuppressWarnings("unchecked") + public T build() { + + if(scheduleBuilder == null) + scheduleBuilder = SimpleScheduleBuilder.simpleSchedule(); + MutableTrigger trig = scheduleBuilder.build(); + + trig.setCalendarName(calendarName); + trig.setDescription(description); + trig.setStartTime(startTime); + trig.setEndTime(endTime); + if(key == null) + key = new TriggerKey(Key.createUniqueName(null), null); + trig.setKey(key); + if(jobKey != null) + trig.setJobKey(jobKey); + trig.setPriority(priority); + + if(!jobDataMap.isEmpty()) + trig.setJobDataMap(jobDataMap); + + return (T) trig; + } + + /** + * Use aTriggerKey
with the given name and default group to + * identify the Trigger. + * + *If none of the 'withIdentity' methods are set on the TriggerBuilder, + * then a random, unique TriggerKey will be generated.
+ * + * @param name the name element for the Trigger's TriggerKey + * @return the updated TriggerBuilder + * @see TriggerKey + * @see Trigger#getKey() + */ + public TriggerBuilderwithIdentity(String name) { + key = new TriggerKey(name, null); + return this; + } + + /** + * Use a TriggerKey with the given name and group to + * identify the Trigger. + * + * If none of the 'withIdentity' methods are set on the TriggerBuilder, + * then a random, unique TriggerKey will be generated.
+ * + * @param name the name element for the Trigger's TriggerKey + * @param group the group element for the Trigger's TriggerKey + * @return the updated TriggerBuilder + * @see TriggerKey + * @see Trigger#getKey() + */ + public TriggerBuilderwithIdentity(String name, String group) { + key = new TriggerKey(name, group); + return this; + } + + /** + * Use the given TriggerKey to identify the Trigger. + * + * If none of the 'withIdentity' methods are set on the TriggerBuilder, + * then a random, unique TriggerKey will be generated.
+ * + * @param triggerKey the TriggerKey for the Trigger to be built + * @return the updated TriggerBuilder + * @see TriggerKey + * @see Trigger#getKey() + */ + public TriggerBuilderwithIdentity(TriggerKey triggerKey) { + this.key = triggerKey; + return this; + } + + /** + * Set the given (human-meaningful) description of the Trigger. + * + * @param triggerDescription the description for the Trigger + * @return the updated TriggerBuilder + * @see Trigger#getDescription() + */ + public TriggerBuilder withDescription(String triggerDescription) { + this.description = triggerDescription; + return this; + } + + /** + * Set the Trigger's priority. When more than one Trigger have the same + * fire time, the scheduler will fire the one with the highest priority + * first. + * + * @param triggerPriority the priority for the Trigger + * @return the updated TriggerBuilder + * @see Trigger#DEFAULT_PRIORITY + * @see Trigger#getPriority() + */ + public TriggerBuilder withPriority(int triggerPriority) { + this.priority = triggerPriority; + return this; + } + + /** + * Set the name of the {@link Calendar} that should be applied to this + * Trigger's schedule. + * + * @param calName the name of the Calendar to reference. + * @return the updated TriggerBuilder + * @see Calendar + * @see Trigger#getCalendarName() + */ + public TriggerBuilder modifiedByCalendar(String calName) { + this.calendarName = calName; + return this; + } + + /** + * Set the time the Trigger should start at - the trigger may or may + * not fire at this time - depending upon the schedule configured for + * the Trigger. However the Trigger will NOT fire before this time, + * regardless of the Trigger's schedule. + * + * @param triggerStartTime the start time for the Trigger. + * @return the updated TriggerBuilder + * @see Trigger#getStartTime() + * @see DateBuilder + */ + public TriggerBuilder startAt(Date triggerStartTime) { + this.startTime = triggerStartTime; + return this; + } + + /** + * Set the time the Trigger should start at to the current moment - + * the trigger may or may not fire at this time - depending upon the + * schedule configured for the Trigger. + * + * @return the updated TriggerBuilder + * @see Trigger#getStartTime() + */ + public TriggerBuilder startNow() { + this.startTime = new Date(); + return this; + } + + /** + * Set the time at which the Trigger will no longer fire - even if it's + * schedule has remaining repeats. + * + * @param triggerEndTime the end time for the Trigger. If null, the end time is indefinite. + * @return the updated TriggerBuilder + * @see Trigger#getEndTime() + * @see DateBuilder + */ + public TriggerBuilder endAt(Date triggerEndTime) { + this.endTime = triggerEndTime; + return this; + } + + /** + * Set the {@link ScheduleBuilder} that will be used to define the + * Trigger's schedule. + * + * The particular
+ * + * @param schedBuilder the SchedulerBuilder to use. + * @return the updated TriggerBuilder + * @see ScheduleBuilder + * @see SimpleScheduleBuilder + * @see CronScheduleBuilder + * @see CalendarIntervalScheduleBuilder + */ + @SuppressWarnings("unchecked") + publicSchedulerBuilder
used will dictate + * the concrete type of Trigger that is produced by the TriggerBuilder.TriggerBuilder withSchedule(ScheduleBuilder schedBuilder) { + this.scheduleBuilder = schedBuilder; + return (TriggerBuilder ) this; + } + + /** + * Set the identity of the Job which should be fired by the produced + * Trigger. + * + * @param keyOfJobToFire the identity of the Job to fire. + * @return the updated TriggerBuilder + * @see Trigger#getJobKey() + */ + public TriggerBuilder forJob(JobKey keyOfJobToFire) { + this.jobKey = keyOfJobToFire; + return this; + } + + /** + * Set the identity of the Job which should be fired by the produced + * Trigger - a JobKey
will be produced with the given + * name and default group. + * + * @param jobName the name of the job (in default group) to fire. + * @return the updated TriggerBuilder + * @see Trigger#getJobKey() + */ + public TriggerBuilderforJob(String jobName) { + this.jobKey = new JobKey(jobName, null); + return this; + } + + /** + * Set the identity of the Job which should be fired by the produced + * Trigger - a JobKey
will be produced with the given + * name and group. + * + * @param jobName the name of the job to fire. + * @param jobGroup the group of the job to fire. + * @return the updated TriggerBuilder + * @see Trigger#getJobKey() + */ + public TriggerBuilderforJob(String jobName, String jobGroup) { + this.jobKey = new JobKey(jobName, jobGroup); + return this; + } + + /** + * Set the identity of the Job which should be fired by the produced + * Trigger, by extracting the JobKey from the given job. + * + * @param jobDetail the Job to fire. + * @return the updated TriggerBuilder + * @see Trigger#getJobKey() + */ + public TriggerBuilder forJob(JobDetail jobDetail) { + JobKey k = jobDetail.getKey(); + if(k.getName() == null) + throw new IllegalArgumentException("The given job has not yet had a name assigned to it."); + this.jobKey = k; + return this; + } + + /** + * Add the given key-value pair to the Trigger's {@link JobDataMap}. + * + * @return the updated TriggerBuilder + * @see Trigger#getJobDataMap() + */ + public TriggerBuilder usingJobData(String dataKey, String value) { + jobDataMap.put(dataKey, value); + return this; + } + + /** + * Add the given key-value pair to the Trigger's {@link JobDataMap}. + * + * @return the updated TriggerBuilder + * @see Trigger#getJobDataMap() + */ + public TriggerBuilder usingJobData(String dataKey, Integer value) { + jobDataMap.put(dataKey, value); + return this; + } + + /** + * Add the given key-value pair to the Trigger's {@link JobDataMap}. + * + * @return the updated TriggerBuilder + * @see Trigger#getJobDataMap() + */ + public TriggerBuilder usingJobData(String dataKey, Long value) { + jobDataMap.put(dataKey, value); + return this; + } + + /** + * Add the given key-value pair to the Trigger's {@link JobDataMap}. + * + * @return the updated TriggerBuilder + * @see Trigger#getJobDataMap() + */ + public TriggerBuilder usingJobData(String dataKey, Float value) { + jobDataMap.put(dataKey, value); + return this; + } + + /** + * Add the given key-value pair to the Trigger's {@link JobDataMap}. + * + * @return the updated TriggerBuilder + * @see Trigger#getJobDataMap() + */ + public TriggerBuilder usingJobData(String dataKey, Double value) { + jobDataMap.put(dataKey, value); + return this; + } + + /** + * Add the given key-value pair to the Trigger's {@link JobDataMap}. + * + * @return the updated TriggerBuilder + * @see Trigger#getJobDataMap() + */ + public TriggerBuilder usingJobData(String dataKey, Boolean value) { + jobDataMap.put(dataKey, value); + return this; + } + + /** + * Set the Trigger's {@link JobDataMap}, adding any values to it + * that were already set on this TriggerBuilder using any of the + * other 'usingJobData' methods. + * + * @return the updated TriggerBuilder + * @see Trigger#getJobDataMap() + */ + public TriggerBuilder usingJobData(JobDataMap newJobDataMap) { + // add any existing data to this new map + for(String dataKey: jobDataMap.keySet()) { + newJobDataMap.put(dataKey, jobDataMap.get(dataKey)); + } + jobDataMap = newJobDataMap; // set new map as the map to use + return this; + } + +} Index: 3rdParty_sources/quartz/org/quartz/TriggerKey.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/TriggerKey.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/TriggerKey.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,78 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +package org.quartz; + +import org.quartz.utils.Key; + +/** + * Uniquely identifies a {@link Trigger}. + * + * Keys are composed of both a name and group, and the name must be unique + * within the group. If only a name is specified then the default group + * name will be used.
+ * + * + *Quartz provides a builder-style API for constructing scheduling-related + * entities via a Domain-Specific Language (DSL). The DSL can best be + * utilized through the usage of static imports of the methods on the classes + *
+ * + *TriggerBuilder
,JobBuilder
, + *DateBuilder
,JobKey
,TriggerKey
+ * and the variousScheduleBuilder
implementations.Client code can then use the DSL to write code such as this:
+ *+ * JobDetail job = newJob(MyJob.class) + * .withIdentity("myJob") + * .build(); + * + * Trigger trigger = newTrigger() + * .withIdentity(triggerKey("myTrigger", "myTriggerGroup")) + * .withSchedule(simpleSchedule() + * .withIntervalInHours(1) + * .repeatForever()) + * .startAt(futureDate(10, MINUTES)) + * .build(); + * + * scheduler.scheduleJob(job, trigger); + *+ * + * + * @see Trigger + * @see Key#DEFAULT_GROUP + */ +public final class TriggerKey extends Key{ + + private static final long serialVersionUID = 8070357886703449660L; + + public TriggerKey(String name) { + super(name, null); + } + + public TriggerKey(String name, String group) { + super(name, group); + } + + public static TriggerKey triggerKey(String name) { + return new TriggerKey(name, null); + } + + public static TriggerKey triggerKey(String name, String group) { + return new TriggerKey(name, group); + } + +} Index: 3rdParty_sources/quartz/org/quartz/TriggerListener.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/TriggerListener.java (.../TriggerListener.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/TriggerListener.java (.../TriggerListener.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,19 +16,17 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; +import org.quartz.Trigger.CompletedExecutionInstruction; + /** - * * The interface to be implemented by classes that want to be informed when a *
* - * @see Scheduler + * @see ListenerManager#addTriggerListener(TriggerListener, Matcher) + * @see Matcher * @see Trigger * @see JobListener * @see JobExecutionContext @@ -50,7 +48,7 @@ * Get the name of the{@link Trigger}
fires. In general, applications that use a *Scheduler
will not have use for this mechanism. - *TriggerListener
. * */ - public String getName(); + String getName(); /** *@@ -70,13 +68,14 @@ * The
JobExecutionContext
that will be passed to * theJob
'sexecute(xx)
method. */ - public void triggerFired(Trigger trigger, JobExecutionContext context); + void triggerFired(Trigger trigger, JobExecutionContext context); /** ** Called by the
* *{@link Scheduler}
when a{@link Trigger}
* has fired, and it's associated{@link org.quartz.JobDetail}
- * is about to be executed. + * is about to be executed. If the implementation vetos the execution (via + * returningtrue
), the job's execute method will not be called. *@@ -90,7 +89,7 @@ * The
JobExecutionContext
that will be passed to * theJob
'sexecute(xx)
method. */ - public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context); + boolean vetoJobExecution(Trigger trigger, JobExecutionContext context); /** @@ -109,7 +108,7 @@ * @param trigger * TheTrigger
that has misfired. */ - public void triggerMisfired(Trigger trigger); + void triggerMisfired(Trigger trigger); /** *@@ -124,11 +123,11 @@ * @param context * The
JobExecutionContext
that was passed to the *Job
'sexecute(xx)
method. - * @param triggerIntructionCode + * @param triggerInstructionCode * the result of the call on theTrigger
'striggered(xx)
* method. */ - public void triggerComplete(Trigger trigger, JobExecutionContext context, - int triggerInstructionCode); + void triggerComplete(Trigger trigger, JobExecutionContext context, + CompletedExecutionInstruction triggerInstructionCode); } Index: 3rdParty_sources/quartz/org/quartz/TriggerUtils.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/TriggerUtils.java (.../TriggerUtils.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/TriggerUtils.java (.../TriggerUtils.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,31 +16,21 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz; -import java.util.Calendar; import java.util.Date; import java.util.LinkedList; import java.util.List; -import java.util.TimeZone; +import org.quartz.spi.OperableTrigger; + /** - *- * Convenience and utility methods for simplifying the construction and - * configuration of
+ * Convenience and utility methods for working with{@link Trigger}s
. - *{@link Trigger}s
. * - *- * Please submit suggestions for additional convenience methods to either the - * Quartz user forum or the developer's mail list at - * source forge. - *
* * @see CronTrigger * @see SimpleTrigger + * @see DateBuilder * * @author James House */ @@ -54,30 +44,12 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - public static final int SUNDAY = 1; - - public static final int MONDAY = 2; - - public static final int TUESDAY = 3; - - public static final int WEDNESDAY = 4; - - public static final int THURSDAY = 5; - - public static final int FRIDAY = 6; - - public static final int SATURDAY = 7; - - public static final int LAST_DAY_OF_MONTH = -1; - - public static final long MILLISECONDS_IN_MINUTE = 60l * 1000l; - - public static final long MILLISECONDS_IN_HOUR = 60l * 60l * 1000l; - - public static final long SECONDS_IN_DAY = 24l * 60l * 60L; - - public static final long MILLISECONDS_IN_DAY = SECONDS_IN_DAY * 1000l; - + /** + * Private constructor because this is a pure utility class. + */ + private TriggerUtils() { + } + /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -86,1134 +58,48 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - private static void validateDayOfWeek(int dayOfWeek) { - if (dayOfWeek < SUNDAY || dayOfWeek > SATURDAY) - throw new IllegalArgumentException("Invalid day of week."); - } - - private static void validateHour(int hour) { - if (hour < 0 || hour > 23) - throw new IllegalArgumentException( - "Invalid hour (must be >= 0 and <= 23)."); - } - - private static void validateMinute(int minute) { - if (minute < 0 || minute > 59) - throw new IllegalArgumentException( - "Invalid minute (must be >= 0 and <= 59)."); - } - - private static void validateSecond(int second) { - if (second < 0 || second > 59) - throw new IllegalArgumentException( - "Invalid second (must be >= 0 and <= 59)."); - } - - private static void validateDayOfMonth(int day) { - if ((day < 1 || day > 31) && day != LAST_DAY_OF_MONTH) - throw new IllegalArgumentException("Invalid day of month."); - } - - private static void validateMonth(int month) { - if (month < 1 || month > 12) - throw new IllegalArgumentException( - "Invalid month (must be >= 1 and <= 12."); - } - - private static void validateYear(int year) { - if (year < 1970 || year > 2099) - throw new IllegalArgumentException( - "Invalid year (must be >= 1970 and <= 2099."); - } - /** - *- * Set the given
+ * Returns a list of Dates that are the next fire times of a + *Trigger
's name to the given value, and its - * group to the default group (Scheduler.DEFAULT_GROUP
). - *Trigger
. + * The input trigger will be cloned before any work is done, so you need + * not worry about its state being altered by this method. * - * @param trig the tigger to change name to - * @param name the new trigger name + * @param trigg + * The trigger upon which to do the work + * @param cal + * The calendar to apply to the trigger's schedule + * @param numTimes + * The number of next fire times to produce + * @return List of java.util.Date objects */ - public static void setTriggerIdentity(Trigger trig, String name) { - setTriggerIdentity(trig, name, Scheduler.DEFAULT_GROUP); - } + public static ListcomputeFireTimes(OperableTrigger trigg, org.quartz.Calendar cal, + int numTimes) { + LinkedList lst = new LinkedList (); - /** - * - * Set the given
- * - * @param trig the tigger to change name to - * @param name the new trigger name - * @param group the new trigger group - */ - public static void setTriggerIdentity( - Trigger trig, String name, String group) { - trig.setName(name); - trig.setGroup(group); - } + OperableTrigger t = (OperableTrigger) trigg.clone(); - /** - *Trigger
's name to the given value, and its - * group to the given group. - *- * Make a trigger that will fire every day at the given time. - *
- * - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param hour the hour (0-23) upon which to fire - * @param minute the minute (0-59) upon which to fire - * @return the new trigger - */ - public static Trigger makeDailyTrigger(int hour, int minute) { - validateHour(hour); - validateMinute(minute); - - CronTrigger trig = new CronTrigger(); - - try { - trig.setCronExpression("0 " + minute + " " + hour + " ? * *"); - } catch (Exception ignore) { - return null; /* never happens... */ + if (t.getNextFireTime() == null) { + t.computeFirstFireTime(cal); } - trig.setStartTime(new Date()); - - return trig; - } - - /** - *- * Make a trigger that will fire every day at the given time. - *
- * - *- * The generated trigger will not have its group or end-time set. - * The Start time defaults to 'now'. - *
- * - * @param trigName the trigger's name - * @param hour the hour (0-23) upon which to fire - * @param minute the minute (0-59) upon which to fire - * @return the newly created trigger - */ - public static Trigger makeDailyTrigger( - String trigName, int hour, int minute) { - Trigger trig = makeDailyTrigger(hour, minute); - trig.setName(trigName); - return trig; - } - - /** - *- * Make a trigger that will fire every week at the given day and time. - *
- * - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param dayOfWeek (1-7) the day of week upon which to fire - * @param hour the hour (0-23) upon which to fire - * @param minute the minute (0-59) upon which to fire - * @return the new trigger - * - * @see #SUNDAY - * @see #MONDAY - * @see #TUESDAY - * @see #WEDNESDAY - * @see #THURSDAY - * @see #FRIDAY - * @see #SATURDAY - */ - public static Trigger makeWeeklyTrigger( - int dayOfWeek, int hour, int minute) { - validateDayOfWeek(dayOfWeek); - validateHour(hour); - validateMinute(minute); - - CronTrigger trig = new CronTrigger(); - - try { - trig.setCronExpression("0 " + minute + " " + hour + " ? * " - + dayOfWeek); - } catch (Exception ignore) { - return null; /* never happens... */ + for (int i = 0; i < numTimes; i++) { + Date d = t.getNextFireTime(); + if (d != null) { + lst.add(d); + t.triggered(cal); + } else { + break; + } } - - trig.setStartTime(new Date()); - return trig; + return java.util.Collections.unmodifiableList(lst); } - - /** - *- * Make a trigger that will fire every week at the given day and time. - *
- * - *- * The generated trigger will not have its group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param trigName the trigger's name - * @param dayOfWeek (1-7) the day of week upon which to fire - * @param hour the hour (0-23) upon which to fire - * @param minute the minute (0-59) upon which to fire - * @return the newly created trigger - * - * @see #SUNDAY - * @see #MONDAY - * @see #TUESDAY - * @see #WEDNESDAY - * @see #THURSDAY - * @see #FRIDAY - * @see #SATURDAY - */ - public static Trigger makeWeeklyTrigger( - String trigName, int dayOfWeek, int hour, int minute) { - Trigger trig = makeWeeklyTrigger(dayOfWeek, hour, minute); - trig.setName(trigName); - return trig; - } - /** - *- * Make a trigger that will fire every month at the given day and time. - *
- * - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * - *- * If the day of the month specified does not occur in a given month, a - * firing will not occur that month. (i.e. if dayOfMonth is specified as - * 31, no firing will occur in the months of the year with fewer than 31 - * days). - *
- * - * @param dayOfMonth (1-31, or -1) the day of week upon which to fire - * @param hour the hour (0-23) upon which to fire - * @param minute the minute (0-59) upon which to fire - * @return the newly created trigger - */ - public static Trigger makeMonthlyTrigger( - int dayOfMonth, int hour, int minute) { - validateDayOfMonth(dayOfMonth); - validateHour(hour); - validateMinute(minute); - - CronTrigger trig = new CronTrigger(); - - try { - if (dayOfMonth != LAST_DAY_OF_MONTH) trig.setCronExpression("0 " - + minute + " " + hour + " " + dayOfMonth + " * ?"); - else - trig.setCronExpression("0 " + minute + " " + hour + " L * ?"); - } catch (Exception ignore) { - return null; /* never happens... */ - } - - trig.setStartTime(new Date()); - - return trig; - } - - /** - *- * Make a trigger that will fire every month at the given day and time. - *
- * - *- * The generated trigger will not have its group, - * or end-time set. The Start time defaults to 'now'. - *
- * - *- * If the day of the month specified does not occur in a given month, a - * firing will not occur that month. (i.e. if dayOfMonth is specified as - * 31, no firing will occur in the months of the year with fewer than 31 - * days). - *
- * - * @param trigName the trigger's name - * @param dayOfMonth (1-31, or -1) the day of week upon which to fire - * @param hour the hour (0-23) upon which to fire - * @param minute the minute (0-59) upon which to fire - * @return the newly created trigger - */ - public static Trigger makeMonthlyTrigger( - String trigName, int dayOfMonth, int hour, int minute) { - Trigger trig = makeMonthlyTrigger(dayOfMonth, hour, minute); - trig.setName(trigName); - return trig; - } - - /* - *Make a trigger that will fire every N days at the given time.
- * - *TThe generated trigger will not have its name, group, - * start-time and end-time set.
- * - * @param hour the hour (0-23) upon which to fire @param minute the minute - * (0-59) upon which to fire @param interval the number of days between - * firings public static Trigger makeDailyTrigger(int interval, int hour, - * int minute) { - * - * SimpleTrigger trig = new SimpleTrigger(); - * - * MILLISECONDS_IN_DAY); - * trig.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY); - * - * return trig; - * } - */ - - /** - *- * Make a trigger that will fire
- * - *repeatCount
times, waiting - *repeatInterval
milliseconds between each fire. - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
+ * Compute theDate
that is 1 second after the Nth firing of + * the givenTrigger
, taking the triger's associated + *Calendar
into consideration. * - * @param repeatCount the number of times to fire the trigger - * @param repeatInterval the number of milliseconds to wait between fires - * @return the newly created trigger - */ - public static Trigger makeImmediateTrigger( - int repeatCount, long repeatInterval) { - SimpleTrigger trig = new SimpleTrigger(); - trig.setStartTime( new Date() ); - trig.setRepeatCount(repeatCount); - trig.setRepeatInterval(repeatInterval); - return trig; - } - - /** - *- * Make a trigger that will fire
- * - *repeatCount
times, waiting - *repeatInterval
milliseconds between each fire. - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param trigName the trigger's name - * @param repeatCount the number of times to fire the trigger - * @param repeatInterval the number of milliseconds to wait between fires - * @return the new trigger - */ - public static Trigger makeImmediateTrigger( - String trigName, int repeatCount, long repeatInterval) { - Trigger trig = makeImmediateTrigger(repeatCount, repeatInterval); - trig.setName(trigName); - return trig; - } - - /** - *- * Make a trigger that will fire every second, indefinitely. - *
- * - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * @return the new trigger - */ - public static Trigger makeSecondlyTrigger() { - return makeSecondlyTrigger(1, SimpleTrigger.REPEAT_INDEFINITELY); - } - - /** - *- * Make a trigger that will fire every second, indefinitely. - *
- * - *- * The generated trigger will not have its group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param trigName the trigger's name - * @return the new trigger - */ - public static Trigger makeSecondlyTrigger(String trigName) { - return makeSecondlyTrigger( - trigName, 1, SimpleTrigger.REPEAT_INDEFINITELY); - } - - - /** - *- * Make a trigger that will fire every N seconds, indefinitely. - *
- * - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param intervalInSeconds the number of seconds between firings - * @return the new trigger - */ - public static Trigger makeSecondlyTrigger(int intervalInSeconds) { - return makeSecondlyTrigger( - intervalInSeconds, SimpleTrigger.REPEAT_INDEFINITELY); - } - - /** - *- * Make a trigger that will fire every N seconds, with the given number of - * repeats. - *
- * - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param intervalInSeconds the number of seconds between firings - * @param repeatCount the number of times to repeat the firing - * @return the new trigger - */ - public static Trigger makeSecondlyTrigger( - int intervalInSeconds, int repeatCount) { - SimpleTrigger trig = new SimpleTrigger(); - - trig.setRepeatInterval(intervalInSeconds * 1000l); - trig.setRepeatCount(repeatCount); - - return trig; - } - - /** - *- * Make a trigger that will fire every N seconds, with the given number of - * repeats. - *
- * - *- * The generated trigger will not have its group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param trigName the trigger's name - * @param intervalInSeconds the number of seconds between firings - * @param repeatCount the number of times to repeat the firing - * @return the new trigger - */ - public static Trigger makeSecondlyTrigger( - String trigName, int intervalInSeconds, int repeatCount) { - Trigger trig = makeSecondlyTrigger(intervalInSeconds, repeatCount); - trig.setName(trigName); - return trig; - } - - /** - *- * Make a trigger that will fire every minute, indefinitely. - *
- * - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @return the new trigger - */ - public static Trigger makeMinutelyTrigger() { - return makeMinutelyTrigger(1, SimpleTrigger.REPEAT_INDEFINITELY); - } - - /** - *- * Make a trigger that will fire every minute, indefinitely. - *
- * - *- * The generated trigger will not have its group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param trigName the trigger's name - * @return the new trigger - */ - public static Trigger makeMinutelyTrigger(String trigName) { - return makeMinutelyTrigger( - trigName, 1, SimpleTrigger.REPEAT_INDEFINITELY); - } - - /** - *- * Make a trigger that will fire every N minutes, indefinitely. - *
- * - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param intervalInMinutes the number of minutes between firings - * @return the new trigger - */ - public static Trigger makeMinutelyTrigger(int intervalInMinutes) { - return makeMinutelyTrigger( - intervalInMinutes, SimpleTrigger.REPEAT_INDEFINITELY); - } - - /** - *- * Make a trigger that will fire every N minutes, with the given number of - * repeats. - *
- * - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param intervalInMinutes the number of minutes between firings - * @param repeatCount the number of times to repeat the firing - * @return the new trigger - */ - public static Trigger makeMinutelyTrigger( - int intervalInMinutes, int repeatCount) { - SimpleTrigger trig = new SimpleTrigger(); - - trig.setRepeatInterval(intervalInMinutes * MILLISECONDS_IN_MINUTE); - trig.setRepeatCount(repeatCount); - - trig.setStartTime(new Date()); - - return trig; - } - - /** - *- * Make a trigger that will fire every N minutes, with the given number of - * repeats. - *
- * - *- * The generated trigger will not have its group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param trigName the trigger's name - * @param intervalInMinutes the number of minutes between firings - * @param repeatCount the number of times to repeat the firing - * @return the new trigger - */ - public static Trigger makeMinutelyTrigger( - String trigName, int intervalInMinutes, int repeatCount) { - Trigger trig = makeMinutelyTrigger(intervalInMinutes, repeatCount); - trig.setName(trigName); - return trig; - } - - /** - *- * Make a trigger that will fire every hour, indefinitely. - *
- * - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @return the new trigger - */ - public static Trigger makeHourlyTrigger() { - return makeHourlyTrigger(1, SimpleTrigger.REPEAT_INDEFINITELY); - } - - /** - *- * Make a trigger that will fire every hour, indefinitely. - *
- * - *- * The generated trigger will not have its group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param trigName the trigger's name - * @return the new trigger - */ - public static Trigger makeHourlyTrigger(String trigName) { - return makeHourlyTrigger( - trigName, 1, SimpleTrigger.REPEAT_INDEFINITELY); - } - - /** - *- * Make a trigger that will fire every N hours, indefinitely. - *
- * - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param intervalInHours the number of hours between firings - * @return the new trigger - */ - public static Trigger makeHourlyTrigger(int intervalInHours) { - return makeHourlyTrigger( - intervalInHours, SimpleTrigger.REPEAT_INDEFINITELY); - } - - /** - *- * Make a trigger that will fire every N hours, with the given number of - * repeats. - *
- * - *- * The generated trigger will not have its name, group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param intervalInHours the number of hours between firings - * @param repeatCount the number of times to repeat the firing - * @return the new trigger - */ - public static Trigger makeHourlyTrigger( - int intervalInHours, int repeatCount) { - SimpleTrigger trig = new SimpleTrigger(); - - trig.setRepeatInterval(intervalInHours * MILLISECONDS_IN_HOUR); - trig.setRepeatCount(repeatCount); - - trig.setStartTime(new Date()); - - return trig; - } - - /** - *- * Make a trigger that will fire every N hours, with the given number of - * repeats. - *
- * - *- * The generated trigger will not have its group, - * or end-time set. The Start time defaults to 'now'. - *
- * - * @param trigName the trigger's name - * @param intervalInHours the number of hours between firings - * @param repeatCount the number of times to repeat the firing - * @return the new trigger - */ - public static Trigger makeHourlyTrigger( - String trigName, int intervalInHours, int repeatCount) { - Trigger trig =makeHourlyTrigger(intervalInHours, repeatCount); - trig.setName(trigName); - return trig; - } - - /** - *- * Returns a date that is rounded to the next even hour above the given - * date. - *
- * - *- * For example an input date with a time of 08:13:54 would result in a date - * with the time of 09:00:00. If the date's time is in the 23rd hour, the - * date's 'day' will be promoted, and the time will be set to 00:00:00. - *
- * - * @param date - * the Date to round, ifnull
the current time will - * be used - * @return the new rounded date - */ - public static Date getEvenHourDate(Date date) { - if (date == null) date = new Date(); - - Calendar c = Calendar.getInstance(); - c.setTime(date); - c.setLenient(true); - - c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY) + 1); - c.set(Calendar.MINUTE, 0); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - - /** - *- * Returns a date that is rounded to the previous even hour below the given - * date. - *
- * - *- * For example an input date with a time of 08:13:54 would result in a date - * with the time of 08:00:00. - *
- * - * @param date - * the Date to round, ifnull
the current time will - * be used - * @return the new rounded date - */ - public static Date getEvenHourDateBefore(Date date) { - if (date == null) date = new Date(); - - Calendar c = Calendar.getInstance(); - c.setTime(date); - - c.set(Calendar.MINUTE, 0); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - - /** - *- * Returns a date that is rounded to the next even minute above the given - * date. - *
- * - *- * For example an input date with a time of 08:13:54 would result in a date - * with the time of 08:14:00. If the date's time is in the 59th minute, - * then the hour (and possibly the day) will be promoted. - *
- * - * @param date - * the Date to round, ifnull
the current time will - * be used - * @return the new rounded date - */ - public static Date getEvenMinuteDate(Date date) { - if (date == null) date = new Date(); - - Calendar c = Calendar.getInstance(); - c.setTime(date); - c.setLenient(true); - - c.set(Calendar.MINUTE, c.get(Calendar.MINUTE) + 1); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - - /** - *- * Returns a date that is rounded to the previous even minute below the - * given date. - *
- * - *- * For example an input date with a time of 08:13:54 would result in a date - * with the time of 08:13:00. - *
- * - * @param date - * the Date to round, ifnull
the current time will - * be used - * @return the new rounded date - */ - public static Date getEvenMinuteDateBefore(Date date) { - if (date == null) date = new Date(); - - Calendar c = Calendar.getInstance(); - c.setTime(date); - - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - - /** - *- * Returns a date that is rounded to the next even second above the given - * date. - *
- * - * @param date - * the Date to round, ifnull
the current time will - * be used - * @return the new rounded date - */ - public static Date getEvenSecondDate(Date date) { - if (date == null) date = new Date(); - - Calendar c = Calendar.getInstance(); - c.setTime(date); - c.setLenient(true); - - c.set(Calendar.SECOND, c.get(Calendar.SECOND) + 1); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - - /** - *- * Returns a date that is rounded to the previous even second below the - * given date. - *
- * - *- * For example an input date with a time of 08:13:54.341 would result in a - * date with the time of 08:13:00.000. - *
- * - * @param date - * the Date to round, ifnull
the current time will - * be used - * @return the new rounded date - */ - public static Date getEvenSecondDateBefore(Date date) { - if (date == null) date = new Date(); - - Calendar c = Calendar.getInstance(); - c.setTime(date); - - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - - /** - *- * Returns a date that is rounded to the next even multiple of the given - * minute. - *
- * - *- * For example an input date with a time of 08:13:54, and an input - * minute-base of 5 would result in a date with the time of 08:15:00. The - * same input date with an input minute-base of 10 would result in a date - * with the time of 08:20:00. But a date with the time 08:53:31 and an - * input minute-base of 45 would result in 09:00:00, because the even-hour - * is the next 'base' for 45-minute intervals. - *
- * - *- * More examples:
- *
- * - * - * @param date - * the Date to round, if- * - *Input Time - *Minute-Base - *Result Time - *- * - *11:16:41 - *20 - *11:20:00 - *- * - *11:36:41 - *20 - *11:40:00 - *- * - *11:46:41 - *20 - *12:00:00 - *- * - *11:26:41 - *30 - *11:30:00 - *- * - *11:36:41 - *30 - *12:00:00 - *11:16:41 - *17 - *11:17:00 - * - * - *11:17:41 - *17 - *11:34:00 - * - * - *11:52:41 - *17 - *12:00:00 - * - * - *11:52:41 - *5 - *11:55:00 - * - * - *11:57:41 - *5 - *12:00:00 - * - * - *11:17:41 - *0 - *12:00:00 - * - * - *11:17:41 - *1 - *11:08:00 - * - *null
the current time will - * be used - * @param minuteBase - * the base-minute to set the time on - * @return the new rounded date - * - * @see #getNextGivenSecondDate(Date, int) - */ - public static Date getNextGivenMinuteDate(Date date, int minuteBase) { - if (minuteBase < 0 || minuteBase > 59) - throw new IllegalArgumentException( - "minuteBase must be >=0 and <= 59"); - - if (date == null) date = new Date(); - - Calendar c = Calendar.getInstance(); - c.setTime(date); - c.setLenient(true); - - if (minuteBase == 0) { - c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY) + 1); - c.set(Calendar.MINUTE, 0); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - - int minute = c.get(Calendar.MINUTE); - - int arItr = minute / minuteBase; - - int nextMinuteOccurance = minuteBase * (arItr + 1); - - if (nextMinuteOccurance < 60) { - c.set(Calendar.MINUTE, nextMinuteOccurance); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } else { - c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY) + 1); - c.set(Calendar.MINUTE, 0); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - } - - /** - *- * Returns a date that is rounded to the next even multiple of the given - * minute. - *
- * - *- * The rules for calculating the second are the same as those for - * calculating the minute in the method - *
- * - * @param date the Date to round, ifgetNextGivenMinuteDate(..)
. - *
null
the current time will - * be used - * @param secondBase the base-second to set the time on - * @return the new rounded date - * - * @see #getNextGivenMinuteDate(Date, int) - */ - public static Date getNextGivenSecondDate(Date date, int secondBase) { - if (secondBase < 0 || secondBase > 59) - throw new IllegalArgumentException( - "secondBase must be >=0 and <= 59"); - - if (date == null) date = new Date(); - - Calendar c = Calendar.getInstance(); - c.setTime(date); - c.setLenient(true); - - if (secondBase == 0) { - c.set(Calendar.MINUTE, c.get(Calendar.MINUTE) + 1); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - - int second = c.get(Calendar.SECOND); - - int arItr = second / secondBase; - - int nextSecondOccurance = secondBase * (arItr + 1); - - if (nextSecondOccurance < 60) { - c.set(Calendar.SECOND, nextSecondOccurance); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } else { - c.set(Calendar.MINUTE, c.get(Calendar.MINUTE) + 1); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - } - - /** - *- * Get a
- * - * @param second - * The value (0-59) to give the seconds field of the date - * @param minute - * The value (0-59) to give the minutes field of the date - * @param hour - * The value (0-23) to give the hours field of the date - * @return the new date - */ - public static Date getDateOf(int second, int minute, int hour) { - validateSecond(second); - validateMinute(minute); - validateHour(hour); - - Date date = new Date(); - - Calendar c = Calendar.getInstance(); - c.setTime(date); - c.setLenient(true); - - c.set(Calendar.HOUR_OF_DAY, hour); - c.set(Calendar.MINUTE, minute); - c.set(Calendar.SECOND, second); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - - /** - *Date
object that represents the given time, on - * today's date. - *- * Get a
- * - * @param second - * The value (0-59) to give the seconds field of the date - * @param minute - * The value (0-59) to give the minutes field of the date - * @param hour - * The value (0-23) to give the hours field of the date - * @param dayOfMonth - * The value (1-31) to give the day of month field of the date - * @param month - * The value (1-12) to give the month field of the date - * @return the new date - */ - public static Date getDateOf(int second, int minute, int hour, - int dayOfMonth, int month) { - validateSecond(second); - validateMinute(minute); - validateHour(hour); - validateDayOfMonth(dayOfMonth); - validateMonth(month); - - Date date = new Date(); - - Calendar c = Calendar.getInstance(); - c.setTime(date); - - c.set(Calendar.MONTH, month - 1); - c.set(Calendar.DAY_OF_MONTH, dayOfMonth); - c.set(Calendar.HOUR_OF_DAY, hour); - c.set(Calendar.MINUTE, minute); - c.set(Calendar.SECOND, second); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - - /** - *Date
object that represents the given time, on the - * given date. - *- * Get a
- * - * @param second - * The value (0-59) to give the seconds field of the date - * @param minute - * The value (0-59) to give the minutes field of the date - * @param hour - * The value (0-23) to give the hours field of the date - * @param dayOfMonth - * The value (1-31) to give the day of month field of the date - * @param month - * The value (1-12) to give the month field of the date - * @param year - * The value (1970-2099) to give the year field of the date - * @return the new date - */ - public static Date getDateOf(int second, int minute, int hour, - int dayOfMonth, int month, int year) { - validateSecond(second); - validateMinute(minute); - validateHour(hour); - validateDayOfMonth(dayOfMonth); - validateMonth(month); - validateYear(year); - - Date date = new Date(); - - Calendar c = Calendar.getInstance(); - c.setTime(date); - - c.set(Calendar.YEAR, year); - c.set(Calendar.MONTH, month - 1); - c.set(Calendar.DAY_OF_MONTH, dayOfMonth); - c.set(Calendar.HOUR_OF_DAY, hour); - c.set(Calendar.MINUTE, minute); - c.set(Calendar.SECOND, second); - c.set(Calendar.MILLISECOND, 0); - - return c.getTime(); - } - - /** - * Returns a list of Dates that are the next fire times of a - *Date
object that represents the given time, on the - * given date. - *Trigger
. * The input trigger will be cloned before any work is done, so you need * not worry about its state being altered by this method. * @@ -1223,28 +109,38 @@ * The calendar to apply to the trigger's schedule * @param numTimes * The number of next fire times to produce - * @return List of java.util.Date objects + * @return the computed Date, or null if the trigger (as configured) will not fire that many times. */ - public static List computeFireTimes(Trigger trigg, org.quartz.Calendar cal, + public static Date computeEndTimeToAllowParticularNumberOfFirings(OperableTrigger trigg, org.quartz.Calendar cal, int numTimes) { - LinkedList lst = new LinkedList(); - Trigger t = (Trigger) trigg.clone(); + OperableTrigger t = (OperableTrigger) trigg.clone(); if (t.getNextFireTime() == null) { t.computeFirstFireTime(cal); } - + + int c = 0; + Date endTime = null; + for (int i = 0; i < numTimes; i++) { Date d = t.getNextFireTime(); if (d != null) { - lst.add(d); + c++; t.triggered(cal); - } else + if(c == numTimes) + endTime = d; + } else { break; + } } - - return java.util.Collections.unmodifiableList(lst); + + if(endTime == null) + return null; + + endTime = new Date(endTime.getTime() + 1000L); + + return endTime; } /** @@ -1256,7 +152,7 @@ * ** NOTE: if this is a trigger that has previously fired within the given - * date range, then firings which have already occured will not be listed + * date range, then firings which have already occurred will not be listed * in the output List. *
* @@ -1270,96 +166,36 @@ * The ending date at which to stop finding fire times * @return List of java.util.Date objects */ - public static List computeFireTimesBetween(Trigger trigg, + public static ListcomputeFireTimesBetween(OperableTrigger trigg, org.quartz.Calendar cal, Date from, Date to) { - LinkedList lst = new LinkedList(); + LinkedList lst = new LinkedList (); - Trigger t = (Trigger) trigg.clone(); + OperableTrigger t = (OperableTrigger) trigg.clone(); if (t.getNextFireTime() == null) { t.setStartTime(from); t.setEndTime(to); t.computeFirstFireTime(cal); } - // TODO: this method could be more efficient by using logic specific - // to the type of trigger ... while (true) { Date d = t.getNextFireTime(); if (d != null) { if (d.before(from)) { t.triggered(cal); continue; } - if (d.after(to)) break; + if (d.after(to)) { + break; + } lst.add(d); t.triggered(cal); - } else + } else { break; + } } return java.util.Collections.unmodifiableList(lst); } - /** - * Translate a date & time from a users timezone to the another - * (probably server) timezone to assist in creating a simple trigger with - * the right date & time. - * - * @param date the date to translate - * @param src the original time-zone - * @param dest the destination time-zone - * @return the translated date - */ - public static Date translateTime(Date date, TimeZone src, TimeZone dest) { - - Date newDate = new Date(); - - int offset = ( - getOffset(date.getTime(), dest) - getOffset(date.getTime(), src) - ); - - newDate.setTime(date.getTime() - offset); - - return newDate; - } - - /** - * Gets the offset from UT for the given date in the given timezone, - * taking into account daylight savings. - * - * - * Equivalent of TimeZone.getOffset(date) in JDK 1.4, but Quartz is trying - * to support JDK 1.3. - *
- * - * @param date the date (in milliseconds) that is the base for the offset - * @param tz the time-zone to calculate to offset to - * @return the offset - */ - public static int getOffset(long date, TimeZone tz) { - - if (tz.inDaylightTime(new Date(date))) { - return tz.getRawOffset() + getDSTSavings(tz); - } - - return tz.getRawOffset(); - } - - /** - *- * Equivalent of TimeZone.getDSTSavings() in JDK 1.4, but Quartz is trying - * to support JDK 1.3. - *
- * - * @param tz the target time-zone - * @return the amount of saving time in milliseconds - */ - public static int getDSTSavings(TimeZone tz) { - - if (tz.useDaylightTime()) { - return 3600000; - } - return 0; - } } Fisheye: Tag c208628989d52041b3765784f4c8cbfd6c80d47b refers to a dead (removed) revision in file `3rdParty_sources/quartz/org/quartz/UICronTrigger.java'. Fisheye: No comparison available. Pass `N' to diff? Index: 3rdParty_sources/quartz/org/quartz/UnableToInterruptJobException.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/UnableToInterruptJobException.java (.../UnableToInterruptJobException.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/UnableToInterruptJobException.java (.../UnableToInterruptJobException.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,23 +16,19 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ - package org.quartz; /** - ** An exception that is thrown to indicate that a call to * InterruptableJob.interrupt() failed without interrupting the Job. - *
* * @see org.quartz.InterruptableJob#interrupt() * * @author James House */ public class UnableToInterruptJobException extends SchedulerException { + + private static final long serialVersionUID = -490863760696463776L; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -56,7 +52,7 @@ * Create aUnableToInterruptJobException
with the given cause. * */ - public UnableToInterruptJobException(Exception cause) { + public UnableToInterruptJobException(Throwable cause) { super(cause); } Index: 3rdParty_sources/quartz/org/quartz/commonj/WorkManagerThreadExecutor.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/commonj/WorkManagerThreadExecutor.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/commonj/WorkManagerThreadExecutor.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,111 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + package org.quartz.commonj; + +import commonj.work.Work; +import commonj.work.WorkManager; +import org.quartz.spi.ThreadExecutor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.naming.InitialContext; +import javax.naming.NamingException; + +/** + * CommonJ WorkManager implementation of hacked Quartz ThreadExecutor class. + * This class schedules work on a WorkManager which is looked up in JNDI. The + * advantage is that all the work performed is done on a managed thread which is + * required by WebSphere, see QUARTZ-743 for + * details. + * + * @author matt.accola + * @version $Revision$ $Date$ + */ +public class WorkManagerThreadExecutor implements ThreadExecutor { + private final Logger log = LoggerFactory.getLogger(getClass()); + + private String workManagerName; + private WorkManager workManager; + + public void execute(Thread thread) { + Work work = new org.quartz.commonj.DelegatingWork(thread); + try { + this.workManager.schedule(work); + } catch (Exception e) { + log.error("Error attempting to schedule QuartzSchedulerThread: " + e.getMessage(), e); + } + } + + public void initialize() { + try { + this.workManager = (WorkManager) new InitialContext().lookup(workManagerName); + } catch (NamingException e) { + throw new IllegalStateException("Could not locate WorkManager: " + e.getMessage(), e); + } + } + + /** + * Sets the JNDI name of the work manager to use. + * + * @param workManagerName the JNDI name to use to lookup the work manager + */ + public void setWorkManagerName(String workManagerName) { + this.workManagerName = workManagerName; + } + +} + +class DelegatingWork implements Work { + + private final Runnable delegate; + + /** + * Create a new DelegatingWork. + * + * @param delegate the Runnable implementation to delegate to + */ + public DelegatingWork(Runnable delegate) { + this.delegate = delegate; + } + + /** + * @return the wrapped Runnable implementation. + */ + public final Runnable getDelegate() { + return this.delegate; + } + + /** + * Delegates execution to the underlying Runnable. + */ + public void run() { + this.delegate.run(); + } + + public boolean isDaemon() { + return false; + } + + /** + * This implementation is empty, since we expect the Runnable to terminate + * based on some specific shutdown signal. + */ + public void release() { + } + +} Index: 3rdParty_sources/quartz/org/quartz/core/JobRunShell.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/core/JobRunShell.java (.../JobRunShell.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/core/JobRunShell.java (.../JobRunShell.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,37 +1,36 @@ -/* - * Copyright 2004-2005 OpenSymphony - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations +/* + * Copyright 2001-2009 Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations * under the License. - * + * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz.core; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.quartz.Job; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; -import org.quartz.JobPersistenceException; import org.quartz.Scheduler; import org.quartz.SchedulerException; -import org.quartz.Trigger; +import org.quartz.Trigger.CompletedExecutionInstruction; +import org.quartz.impl.JobExecutionContextImpl; +import org.quartz.listeners.SchedulerListenerSupport; +import org.quartz.spi.OperableTrigger; import org.quartz.spi.TriggerFiredBundle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** *@@ -41,372 +40,343 @@ * the
- * + * *Trigger
with theJob
's completion code, * etc. ** A
- * + * * @see JobRunShellFactory * @see org.quartz.core.QuartzSchedulerThread * @see org.quartz.Job * @see org.quartz.Trigger - * + * * @author James House */ -public class JobRunShell implements Runnable { +public class JobRunShell extends SchedulerListenerSupport implements Runnable { /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * + * * Data members. - * + * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - protected JobExecutionContext jec = null; + protected JobExecutionContextImpl jec = null; protected QuartzScheduler qs = null; + + protected TriggerFiredBundle firedTriggerBundle = null; protected Scheduler scheduler = null; - protected SchedulingContext schdCtxt = null; + protected volatile boolean shutdownRequested = false; - protected JobRunShellFactory jobRunShellFactory = null; + private final Logger log = LoggerFactory.getLogger(getClass()); - protected boolean shutdownRequested = false; - - protected Log log = LogFactory.getLog(getClass()); - /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * + * * Constructors. - * + * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** *JobRunShell
instance is created by aJobRunShellFactory
* on behalf of theQuartzSchedulerThread
which then runs the * shell in a thread from the configuredThreadPool
when the * scheduler determines that aJob
has been triggered. ** Create a JobRunShell instance with the given settings. *
- * - * @param jobRunShellFactory - * A handle to theJobRunShellFactory
that produced - * thisJobRunShell
. + * * @param scheduler * TheScheduler
instance that should be made * available within theJobExecutionContext
. - * @param schdCtxt - * theSchedulingContext
that should be used by the - *JobRunShell
when making updates to theJobStore
. */ - public JobRunShell(JobRunShellFactory jobRunShellFactory, - Scheduler scheduler, SchedulingContext schdCtxt) { - this.jobRunShellFactory = jobRunShellFactory; + public JobRunShell(Scheduler scheduler, TriggerFiredBundle bndle) { this.scheduler = scheduler; - this.schdCtxt = schdCtxt; + this.firedTriggerBundle = bndle; } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * + * * Interface. - * + * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - private static Log getLog() - { - return LogFactory.getLog(JobRunShell.class); + @Override + public void schedulerShuttingdown() { + requestShutdown(); } - - public void initialize(QuartzScheduler qs, TriggerFiredBundle firedBundle) - throws SchedulerException { - this.qs = qs; + @Override + protected Logger getLog() { + return log; + } + + public void initialize(QuartzScheduler sched) + throws SchedulerException { + this.qs = sched; + Job job = null; - JobDetail jobDetail = firedBundle.getJobDetail(); + JobDetail jobDetail = firedTriggerBundle.getJobDetail(); try { - job = qs.getJobFactory().newJob(firedBundle); + job = sched.getJobFactory().newJob(firedTriggerBundle, scheduler); } catch (SchedulerException se) { - qs.notifySchedulerListenersError( + sched.notifySchedulerListenersError( "An error occured instantiating job to be executed. job= '" - + jobDetail.getFullName() + "'", se); + + jobDetail.getKey() + "'", se); throw se; - } catch (Exception e) { - SchedulerException se = new SchedulerException( - "Problem instantiating class '" - + jobDetail.getJobClass().getName() + "'", e); - qs.notifySchedulerListenersError( - "An error occured instantiating job to be executed. job= '" - + jobDetail.getFullName() + "'", se); - throw se; } catch (Throwable ncdfe) { // such as NoClassDefFoundError SchedulerException se = new SchedulerException( "Problem instantiating class '" - + jobDetail.getJobClass().getName() + "' - " + ncdfe); - qs.notifySchedulerListenersError( + + jobDetail.getJobClass().getName() + "' - ", ncdfe); + sched.notifySchedulerListenersError( "An error occured instantiating job to be executed. job= '" - + jobDetail.getFullName() + "'", se); + + jobDetail.getKey() + "'", se); throw se; } - this.jec = new JobExecutionContext(scheduler, firedBundle, job); + this.jec = new JobExecutionContextImpl(scheduler, firedTriggerBundle, job); } public void requestShutdown() { shutdownRequested = true; } public void run() { - Trigger trigger = jec.getTrigger(); - JobDetail jobDetail = jec.getJobDetail(); + qs.addInternalSchedulerListener(this); - do { + try { + OperableTrigger trigger = (OperableTrigger) jec.getTrigger(); + JobDetail jobDetail = jec.getJobDetail(); - JobExecutionException jobExEx = null; - Job job = jec.getJobInstance(); + do { - try { - begin(); - } catch (SchedulerException se) { - qs.notifySchedulerListenersError("Error executing Job (" - + jec.getJobDetail().getFullName() - + ": couldn't begin execution.", se); - break; - } + JobExecutionException jobExEx = null; + Job job = jec.getJobInstance(); - // notify job & trigger listeners... - try { - if (!notifyListenersBeginning(jec)) break; - } - catch(VetoedException ve) { try { - complete(true); + begin(); } catch (SchedulerException se) { - qs.notifySchedulerListenersError("Error during veto of Job (" - + jec.getJobDetail().getFullName() - + ": couldn't finalize execution.", se); + qs.notifySchedulerListenersError("Error executing Job (" + + jec.getJobDetail().getKey() + + ": couldn't begin execution.", se); + break; } - break; - } - long startTime = System.currentTimeMillis(); - long endTime = startTime; - - // execute the job - try { - log.debug("Calling execute on job " + jobDetail.getFullName()); - job.execute(jec); - endTime = System.currentTimeMillis(); - } catch (JobExecutionException jee) { - endTime = System.currentTimeMillis(); - jobExEx = jee; - getLog().info("Job " + jobDetail.getFullName() + - " threw a JobExecutionException: ", jobExEx); - } catch (Exception e) { - endTime = System.currentTimeMillis(); - getLog().error("Job " + jobDetail.getFullName() + - " threw an unhandled Exception: ", e); - SchedulerException se = new SchedulerException( - "Job threw an unhandled exception.", e); - se.setErrorCode(SchedulerException.ERR_JOB_EXECUTION_THREW_EXCEPTION); - qs.notifySchedulerListenersError("Job (" - + jec.getJobDetail().getFullName() - + " threw an exception.", se); - jobExEx = new JobExecutionException(se, false); - jobExEx.setErrorCode(JobExecutionException.ERR_JOB_EXECUTION_THREW_EXCEPTION); - } - - jec.setJobRunTime(endTime - startTime); + // notify job & trigger listeners... + try { + if (!notifyListenersBeginning(jec)) { + break; + } + } catch(VetoedException ve) { + try { + CompletedExecutionInstruction instCode = trigger.executionComplete(jec, null); + qs.notifyJobStoreJobVetoed(trigger, jobDetail, instCode); + + // QTZ-205 + // Even if trigger got vetoed, we still needs to check to see if it's the trigger's finalized run or not. + if (jec.getTrigger().getNextFireTime() == null) { + qs.notifySchedulerListenersFinalized(jec.getTrigger()); + } - // notify all job listeners - if (!notifyJobListenersComplete(jec, jobExEx)) break; + complete(true); + } catch (SchedulerException se) { + qs.notifySchedulerListenersError("Error during veto of Job (" + + jec.getJobDetail().getKey() + + ": couldn't finalize execution.", se); + } + break; + } - int instCode = Trigger.INSTRUCTION_NOOP; + long startTime = System.currentTimeMillis(); + long endTime = startTime; - // update the trigger - try { - instCode = trigger.executionComplete(jec, jobExEx); - } catch (Exception e) { - // If this happens, there's a bug in the trigger... - SchedulerException se = new SchedulerException( - "Trigger threw an unhandled exception.", e); - se.setErrorCode(SchedulerException.ERR_TRIGGER_THREW_EXCEPTION); - qs.notifySchedulerListenersError( - "Please report this error to the Quartz developers.", - se); - } + // execute the job + try { + log.debug("Calling execute on job " + jobDetail.getKey()); + job.execute(jec); + endTime = System.currentTimeMillis(); + } catch (JobExecutionException jee) { + endTime = System.currentTimeMillis(); + jobExEx = jee; + getLog().info("Job " + jobDetail.getKey() + + " threw a JobExecutionException: ", jobExEx); + } catch (Throwable e) { + endTime = System.currentTimeMillis(); + getLog().error("Job " + jobDetail.getKey() + + " threw an unhandled Exception: ", e); + SchedulerException se = new SchedulerException( + "Job threw an unhandled exception.", e); + qs.notifySchedulerListenersError("Job (" + + jec.getJobDetail().getKey() + + " threw an exception.", se); + jobExEx = new JobExecutionException(se, false); + } - // notify all trigger listeners - if (!notifyTriggerListenersComplete(jec, instCode)) break; + jec.setJobRunTime(endTime - startTime); - // update job/trigger or re-execute job - if (instCode == Trigger.INSTRUCTION_RE_EXECUTE_JOB) { - jec.incrementRefireCount(); + // notify all job listeners + if (!notifyJobListenersComplete(jec, jobExEx)) { + break; + } + + CompletedExecutionInstruction instCode = CompletedExecutionInstruction.NOOP; + + // update the trigger try { - complete(false); + instCode = trigger.executionComplete(jec, jobExEx); + } catch (Exception e) { + // If this happens, there's a bug in the trigger... + SchedulerException se = new SchedulerException( + "Trigger threw an unhandled exception.", e); + qs.notifySchedulerListenersError( + "Please report this error to the Quartz developers.", + se); + } + + // notify all trigger listeners + if (!notifyTriggerListenersComplete(jec, instCode)) { + break; + } + + // update job/trigger or re-execute job + if (instCode == CompletedExecutionInstruction.RE_EXECUTE_JOB) { + jec.incrementRefireCount(); + try { + complete(false); + } catch (SchedulerException se) { + qs.notifySchedulerListenersError("Error executing Job (" + + jec.getJobDetail().getKey() + + ": couldn't finalize execution.", se); + } + continue; + } + + try { + complete(true); } catch (SchedulerException se) { qs.notifySchedulerListenersError("Error executing Job (" - + jec.getJobDetail().getFullName() + + jec.getJobDetail().getKey() + ": couldn't finalize execution.", se); + continue; } - continue; - } - try { - complete(true); - } catch (SchedulerException se) { - qs.notifySchedulerListenersError("Error executing Job (" - + jec.getJobDetail().getFullName() - + ": couldn't finalize execution.", se); - continue; - } + qs.notifyJobStoreJobComplete(trigger, jobDetail, instCode); + break; + } while (true); - try { - qs.notifyJobStoreJobComplete(schdCtxt, trigger, jobDetail, - instCode); - } catch (JobPersistenceException jpe) { - qs.notifySchedulerListenersError( - "An error occured while marking executed job complete. job= '" - + jobDetail.getFullName() + "'", jpe); - if (!completeTriggerRetryLoop(trigger, jobDetail, instCode)) - ; - return; - } - - break; - } while (true); - - qs.notifySchedulerThread(); - - jobRunShellFactory.returnJobRunShell(this); + } finally { + qs.removeInternalSchedulerListener(this); + } } protected void begin() throws SchedulerException { } protected void complete(boolean successfulExecution) - throws SchedulerException { + throws SchedulerException { } public void passivate() { jec = null; qs = null; } - private boolean notifyListenersBeginning(JobExecutionContext jec) throws VetoedException { - + private boolean notifyListenersBeginning(JobExecutionContext jobExCtxt) throws VetoedException { + boolean vetoed = false; - + // notify all trigger listeners try { - vetoed = qs.notifyTriggerListenersFired(jec); + vetoed = qs.notifyTriggerListenersFired(jobExCtxt); } catch (SchedulerException se) { qs.notifySchedulerListenersError( "Unable to notify TriggerListener(s) while firing trigger " + "(Trigger and Job will NOT be fired!). trigger= " - + jec.getTrigger().getFullName() + " job= " - + jec.getJobDetail().getFullName(), se); + + jobExCtxt.getTrigger().getKey() + " job= " + + jobExCtxt.getJobDetail().getKey(), se); return false; } if(vetoed) { try { - qs.notifyJobListenersWasVetoed(jec); + qs.notifyJobListenersWasVetoed(jobExCtxt); } catch (SchedulerException se) { qs.notifySchedulerListenersError( "Unable to notify JobListener(s) of vetoed execution " + "while firing trigger (Trigger and Job will NOT be " + "fired!). trigger= " - + jec.getTrigger().getFullName() + " job= " - + jec.getJobDetail().getFullName(), se); + + jobExCtxt.getTrigger().getKey() + " job= " + + jobExCtxt.getJobDetail().getKey(), se); } throw new VetoedException(); } - + // notify all job listeners try { - qs.notifyJobListenersToBeExecuted(jec); + qs.notifyJobListenersToBeExecuted(jobExCtxt); } catch (SchedulerException se) { qs.notifySchedulerListenersError( "Unable to notify JobListener(s) of Job to be executed: " + "(Job will NOT be executed!). trigger= " - + jec.getTrigger().getFullName() + " job= " - + jec.getJobDetail().getFullName(), se); + + jobExCtxt.getTrigger().getKey() + " job= " + + jobExCtxt.getJobDetail().getKey(), se); return false; } return true; } - private boolean notifyJobListenersComplete(JobExecutionContext jec, - JobExecutionException jobExEx) { + private boolean notifyJobListenersComplete(JobExecutionContext jobExCtxt, JobExecutionException jobExEx) { try { - qs.notifyJobListenersWasExecuted(jec, jobExEx); + qs.notifyJobListenersWasExecuted(jobExCtxt, jobExEx); } catch (SchedulerException se) { qs.notifySchedulerListenersError( "Unable to notify JobListener(s) of Job that was executed: " + "(error will be ignored). trigger= " - + jec.getTrigger().getFullName() + " job= " - + jec.getJobDetail().getFullName(), se); + + jobExCtxt.getTrigger().getKey() + " job= " + + jobExCtxt.getJobDetail().getKey(), se); return false; } return true; } - private boolean notifyTriggerListenersComplete(JobExecutionContext jec, - int instCode) { + private boolean notifyTriggerListenersComplete(JobExecutionContext jobExCtxt, CompletedExecutionInstruction instCode) { try { - qs.notifyTriggerListenersComplete(jec, instCode); + qs.notifyTriggerListenersComplete(jobExCtxt, instCode); } catch (SchedulerException se) { qs.notifySchedulerListenersError( "Unable to notify TriggerListener(s) of Job that was executed: " + "(error will be ignored). trigger= " - + jec.getTrigger().getFullName() + " job= " - + jec.getJobDetail().getFullName(), se); + + jobExCtxt.getTrigger().getKey() + " job= " + + jobExCtxt.getJobDetail().getKey(), se); return false; } - if (jec.getTrigger().getNextFireTime() == null) - qs.notifySchedulerListenersFinalized(jec.getTrigger()); + if (jobExCtxt.getTrigger().getNextFireTime() == null) { + qs.notifySchedulerListenersFinalized(jobExCtxt.getTrigger()); + } return true; } - public boolean completeTriggerRetryLoop(Trigger trigger, - JobDetail jobDetail, int instCode) { - while (!shutdownRequested) { - try { - Thread.sleep(5 * 1000l); // retry every 5 seconds (the db - // connection must be failed) - qs.notifyJobStoreJobComplete(schdCtxt, trigger, jobDetail, - instCode); - return true; - } catch (JobPersistenceException jpe) { - qs.notifySchedulerListenersError( - "An error occured while marking executed job complete. job= '" - + jobDetail.getFullName() + "'", jpe); - } catch (InterruptedException ignore) { - } - } - return false; - } + static class VetoedException extends Exception { - - class VetoedException extends Exception - { - public VetoedException() - { + private static final long serialVersionUID = 1539955697495918463L; + + public VetoedException() { } } -} \ No newline at end of file + +} Index: 3rdParty_sources/quartz/org/quartz/core/JobRunShellFactory.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/core/JobRunShellFactory.java (.../JobRunShellFactory.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/core/JobRunShellFactory.java (.../JobRunShellFactory.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,29 +16,19 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz.core; import org.quartz.Scheduler; import org.quartz.SchedulerConfigException; import org.quartz.SchedulerException; +import org.quartz.spi.TriggerFiredBundle; /** ** Responsible for creating the instances of
* - *{@link JobRunShell}
* to be used within the{@link QuartzScheduler} instance. * - * Although this interface looks a lot like an 'object pool', implementations - * do not have to support the re-use of instances. If an implementation does - * not wish to pool instances, then the
- * * @author James House */ public interface JobRunShellFactory { @@ -55,28 +45,17 @@ *borrowJobRunShell()
- * method would simply create a new instance, and thereturnJobRunShell - *
method would do nothing. - ** Initialize the factory, providing a handle to the
*/ - public void initialize(Scheduler scheduler, SchedulingContext schedCtxt) - throws SchedulerConfigException; + void initialize(Scheduler scheduler) + throws SchedulerConfigException; /** *Scheduler
* that should be made available within theJobRunShell
and - * theJobExecutionCOntext
s within it, and a handle to the - *SchedulingContext
that the shell will use in its own - * operations with theJobStore
. + * theJobExecutionContext
s within it. ** Called by the
*/ - public JobRunShell borrowJobRunShell() throws SchedulerException; - - /** - *{@link org.quartz.core.QuartzSchedulerThread}
* to obtain instances of{@link JobRunShell}
. *- * Called by the
- */ - public void returnJobRunShell(JobRunShell jobRunShell); - + JobRunShell createJobRunShell(TriggerFiredBundle bundle) throws SchedulerException; } \ No newline at end of file Index: 3rdParty_sources/quartz/org/quartz/core/ListenerManagerImpl.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/core/ListenerManagerImpl.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/core/ListenerManagerImpl.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,275 @@ +package org.quartz.core; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.quartz.JobKey; +import org.quartz.JobListener; +import org.quartz.ListenerManager; +import org.quartz.Matcher; +import org.quartz.SchedulerListener; +import org.quartz.TriggerKey; +import org.quartz.TriggerListener; +import org.quartz.impl.matchers.EverythingMatcher; + +public class ListenerManagerImpl implements ListenerManager { + + private Map{@link org.quartz.core.QuartzSchedulerThread}
- * to return instances of{@link JobRunShell}
. - *globalJobListeners = new LinkedHashMap (10); + + private Map globalTriggerListeners = new LinkedHashMap (10); + + private Map >> globalJobListenersMatchers = new LinkedHashMap >>(10); + + private Map >> globalTriggerListenersMatchers = new LinkedHashMap >>(10); + + private ArrayList schedulerListeners = new ArrayList (10); + + + public void addJobListener(JobListener jobListener, Matcher ... matchers) { + addJobListener(jobListener, Arrays.asList(matchers)); + } + + public void addJobListener(JobListener jobListener, List > matchers) { + if (jobListener.getName() == null || jobListener.getName().length() == 0) { + throw new IllegalArgumentException( + "JobListener name cannot be empty."); + } + + synchronized (globalJobListeners) { + globalJobListeners.put(jobListener.getName(), jobListener); + LinkedList > matchersL = new LinkedList >(); + if(matchers != null && matchers.size() > 0) + matchersL.addAll(matchers); + else + matchersL.add(EverythingMatcher.allJobs()); + + globalJobListenersMatchers.put(jobListener.getName(), matchersL); + } + } + + + public void addJobListener(JobListener jobListener) { + addJobListener(jobListener, EverythingMatcher.allJobs()); + } + + public void addJobListener(JobListener jobListener, Matcher matcher) { + if (jobListener.getName() == null || jobListener.getName().length() == 0) { + throw new IllegalArgumentException( + "JobListener name cannot be empty."); + } + + synchronized (globalJobListeners) { + globalJobListeners.put(jobListener.getName(), jobListener); + LinkedList > matchersL = new LinkedList >(); + if(matcher != null) + matchersL.add(matcher); + else + matchersL.add(EverythingMatcher.allJobs()); + + globalJobListenersMatchers.put(jobListener.getName(), matchersL); + } + } + + + public boolean addJobListenerMatcher(String listenerName, Matcher matcher) { + if(matcher == null) + throw new IllegalArgumentException("Null value not acceptable."); + + synchronized (globalJobListeners) { + List > matchers = globalJobListenersMatchers.get(listenerName); + if(matchers == null) + return false; + matchers.add(matcher); + return true; + } + } + + public boolean removeJobListenerMatcher(String listenerName, Matcher matcher) { + if(matcher == null) + throw new IllegalArgumentException("Non-null value not acceptable."); + + synchronized (globalJobListeners) { + List > matchers = globalJobListenersMatchers.get(listenerName); + if(matchers == null) + return false; + return matchers.remove(matcher); + } + } + + public List > getJobListenerMatchers(String listenerName) { + synchronized (globalJobListeners) { + List > matchers = globalJobListenersMatchers.get(listenerName); + if(matchers == null) + return null; + return Collections.unmodifiableList(matchers); + } + } + + public boolean setJobListenerMatchers(String listenerName, List > matchers) { + if(matchers == null) + throw new IllegalArgumentException("Non-null value not acceptable."); + + synchronized (globalJobListeners) { + List > oldMatchers = globalJobListenersMatchers.get(listenerName); + if(oldMatchers == null) + return false; + globalJobListenersMatchers.put(listenerName, matchers); + return true; + } + } + + + public boolean removeJobListener(String name) { + synchronized (globalJobListeners) { + return (globalJobListeners.remove(name) != null); + } + } + + public List getJobListeners() { + synchronized (globalJobListeners) { + return java.util.Collections.unmodifiableList(new LinkedList (globalJobListeners.values())); + } + } + + public JobListener getJobListener(String name) { + synchronized (globalJobListeners) { + return globalJobListeners.get(name); + } + } + + public void addTriggerListener(TriggerListener triggerListener, Matcher ... matchers) { + addTriggerListener(triggerListener, Arrays.asList(matchers)); + } + + public void addTriggerListener(TriggerListener triggerListener, List > matchers) { + if (triggerListener.getName() == null + || triggerListener.getName().length() == 0) { + throw new IllegalArgumentException( + "TriggerListener name cannot be empty."); + } + + synchronized (globalTriggerListeners) { + globalTriggerListeners.put(triggerListener.getName(), triggerListener); + + LinkedList > matchersL = new LinkedList >(); + if(matchers != null && matchers.size() > 0) + matchersL.addAll(matchers); + else + matchersL.add(EverythingMatcher.allTriggers()); + + globalTriggerListenersMatchers.put(triggerListener.getName(), matchersL); + } + } + + public void addTriggerListener(TriggerListener triggerListener) { + addTriggerListener(triggerListener, EverythingMatcher.allTriggers()); + } + + public void addTriggerListener(TriggerListener triggerListener, Matcher matcher) { + if(matcher == null) + throw new IllegalArgumentException("Null value not acceptable for matcher."); + + if (triggerListener.getName() == null + || triggerListener.getName().length() == 0) { + throw new IllegalArgumentException( + "TriggerListener name cannot be empty."); + } + + synchronized (globalTriggerListeners) { + globalTriggerListeners.put(triggerListener.getName(), triggerListener); + List > matchers = new LinkedList >(); + matchers.add(matcher); + globalTriggerListenersMatchers.put(triggerListener.getName(), matchers); + } + } + + public boolean addTriggerListenerMatcher(String listenerName, Matcher matcher) { + if(matcher == null) + throw new IllegalArgumentException("Non-null value not acceptable."); + + synchronized (globalTriggerListeners) { + List > matchers = globalTriggerListenersMatchers.get(listenerName); + if(matchers == null) + return false; + matchers.add(matcher); + return true; + } + } + + public boolean removeTriggerListenerMatcher(String listenerName, Matcher matcher) { + if(matcher == null) + throw new IllegalArgumentException("Non-null value not acceptable."); + + synchronized (globalTriggerListeners) { + List > matchers = globalTriggerListenersMatchers.get(listenerName); + if(matchers == null) + return false; + return matchers.remove(matcher); + } + } + + public List > getTriggerListenerMatchers(String listenerName) { + synchronized (globalTriggerListeners) { + List > matchers = globalTriggerListenersMatchers.get(listenerName); + if(matchers == null) + return null; + return Collections.unmodifiableList(matchers); + } + } + + public boolean setTriggerListenerMatchers(String listenerName, List > matchers) { + if(matchers == null) + throw new IllegalArgumentException("Non-null value not acceptable."); + + synchronized (globalTriggerListeners) { + List > oldMatchers = globalTriggerListenersMatchers.get(listenerName); + if(oldMatchers == null) + return false; + globalTriggerListenersMatchers.put(listenerName, matchers); + return true; + } + } + + public boolean removeTriggerListener(String name) { + synchronized (globalTriggerListeners) { + return (globalTriggerListeners.remove(name) != null); + } + } + + + public List getTriggerListeners() { + synchronized (globalTriggerListeners) { + return java.util.Collections.unmodifiableList(new LinkedList (globalTriggerListeners.values())); + } + } + + public TriggerListener getTriggerListener(String name) { + synchronized (globalTriggerListeners) { + return globalTriggerListeners.get(name); + } + } + + + public void addSchedulerListener(SchedulerListener schedulerListener) { + synchronized (schedulerListeners) { + schedulerListeners.add(schedulerListener); + } + } + + public boolean removeSchedulerListener(SchedulerListener schedulerListener) { + synchronized (schedulerListeners) { + return schedulerListeners.remove(schedulerListener); + } + } + + public List getSchedulerListeners() { + synchronized (schedulerListeners) { + return java.util.Collections.unmodifiableList(new ArrayList (schedulerListeners)); + } + } +} Index: 3rdParty_sources/quartz/org/quartz/core/NullSampledStatisticsImpl.java =================================================================== diff -u --- 3rdParty_sources/quartz/org/quartz/core/NullSampledStatisticsImpl.java (revision 0) +++ 3rdParty_sources/quartz/org/quartz/core/NullSampledStatisticsImpl.java (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -0,0 +1,19 @@ +package org.quartz.core; + +public class NullSampledStatisticsImpl implements SampledStatistics { + public long getJobsCompletedMostRecentSample() { + return 0; + } + + public long getJobsExecutingMostRecentSample() { + return 0; + } + + public long getJobsScheduledMostRecentSample() { + return 0; + } + + public void shutdown() { + // nothing to do + } +} Index: 3rdParty_sources/quartz/org/quartz/core/QuartzScheduler.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc208628989d52041b3765784f4c8cbfd6c80d47b --- 3rdParty_sources/quartz/org/quartz/core/QuartzScheduler.java (.../QuartzScheduler.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/quartz/org/quartz/core/QuartzScheduler.java (.../QuartzScheduler.java) (revision c208628989d52041b3765784f4c8cbfd6c80d47b) @@ -1,6 +1,6 @@ /* - * Copyright 2004-2005 OpenSymphony + * Copyright 2001-2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -16,58 +16,76 @@ * */ -/* - * Previously Copyright (c) 2001-2004 James House - */ package org.quartz.core; -import java.io.IOException; import java.io.InputStream; +import java.lang.management.ManagementFactory; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; -import java.util.Collections; +import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.Random; import java.util.Set; +import java.util.Timer; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicInteger; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import javax.management.MBeanServer; +import javax.management.ObjectName; + import org.quartz.Calendar; import org.quartz.InterruptableJob; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; +import org.quartz.JobKey; import org.quartz.JobListener; -import org.quartz.JobPersistenceException; +import org.quartz.ListenerManager; +import org.quartz.Matcher; import org.quartz.ObjectAlreadyExistsException; import org.quartz.Scheduler; import org.quartz.SchedulerContext; import org.quartz.SchedulerException; import org.quartz.SchedulerListener; +import org.quartz.SchedulerMetaData; import org.quartz.Trigger; +import static org.quartz.TriggerBuilder.*; +import org.quartz.TriggerKey; import org.quartz.TriggerListener; import org.quartz.UnableToInterruptJobException; +import org.quartz.Trigger.CompletedExecutionInstruction; +import org.quartz.Trigger.TriggerState; +import org.quartz.core.jmx.QuartzSchedulerMBean; import org.quartz.impl.SchedulerRepository; -import org.quartz.simpl.SimpleJobFactory; +import org.quartz.impl.StdSchedulerFactory; +import org.quartz.impl.matchers.GroupMatcher; +import org.quartz.listeners.SchedulerListenerSupport; +import org.quartz.simpl.PropertySettingJobFactory; import org.quartz.spi.JobFactory; +import org.quartz.spi.OperableTrigger; import org.quartz.spi.SchedulerPlugin; import org.quartz.spi.SchedulerSignaler; +import org.quartz.spi.ThreadExecutor; +import org.quartz.utils.UpdateChecker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * * This is the heart of Quartz, an indirect implementation of the
// TODO: more docs... + * * * @see org.quartz.Scheduler * @see org.quartz.core.QuartzSchedulerThread @@ -92,17 +110,32 @@ static { Properties props = new Properties(); + InputStream is = null; try { - InputStream is = - QuartzScheduler.class.getResourceAsStream("/build.properties"); + is = QuartzScheduler.class.getResourceAsStream("quartz-build.properties"); if(is != null) { props.load(is); - VERSION_MAJOR = props.getProperty("version.major"); - VERSION_MINOR = props.getProperty("version.minor"); - VERSION_ITERATION = props.getProperty("version.iter"); + String version = props.getProperty("version"); + if (version != null) { + String[] versionComponents = version.split("\\."); + VERSION_MAJOR = versionComponents[0]; + VERSION_MINOR = versionComponents[1]; + if(versionComponents.length > 2) + VERSION_ITERATION = versionComponents[2]; + else + VERSION_ITERATION = "0"; + } else { + (LoggerFactory.getLogger(QuartzScheduler.class)).error( + "Can't parse Quartz version from quartz-build.properties"); + } } - } catch (IOException e) { - getLog().error("Error loading version info from build.properties.", e); + } catch (Exception e) { + (LoggerFactory.getLogger(QuartzScheduler.class)).error( + "Error loading version info from quartz-build.properties.", e); + } finally { + if(is != null) { + try { is.close(); } catch(Exception ignore) {} + } } } @@ -123,19 +156,15 @@ private SchedulerContext context = new SchedulerContext(); - private HashMap jobListeners = new HashMap(10); + private ListenerManager listenerManager = new ListenerManagerImpl(); + + private HashMap{@link org.quartz.Scheduler}
* interface, containing methods to schedule{@link org.quartz.Job}
s, * register{@link org.quartz.JobListener}
instances, etc. - *internalJobListeners = new HashMap (10); - private ArrayList globalJobListeners = new ArrayList(10); + private HashMap internalTriggerListeners = new HashMap (10); - private HashMap triggerListeners = new HashMap(10); + private ArrayList internalSchedulerListeners = new ArrayList (10); - private ArrayList globalTriggerListeners = new ArrayList(10); - - private ArrayList schedulerListeners = new ArrayList(10); - - private ArrayList schedulerPlugins = new ArrayList(10); - - private JobFactory jobFactory = new SimpleJobFactory(); + private JobFactory jobFactory = new PropertySettingJobFactory(); ExecutingJobsManager jobMgr = null; @@ -145,14 +174,27 @@ private Random random = new Random(); - private ArrayList holdToPreventGC = new ArrayList(5); + private ArrayList