📄 uicrontrigger.java
字号:
/* * UICronTrigger.java * * Based on work in Quartz: Copyright James House (c) 2001-2004 * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: 1. * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. 2. Redistributions in * binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */package org.quartz;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.quartz.Scheduler;import org.quartz.SimpleTrigger;import org.quartz.Trigger;import org.quartz.CronTrigger;import java.util.Calendar;import java.util.Date;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;import java.util.SortedSet;import java.util.TimeZone;import java.util.TreeSet;import java.text.ParseException;/** * <p> * A concrete <code>{@link Trigger}</code> that is used to fire a <code>{@link Job}</code> * at given moments in time, defined with Unix 'cron-like' definitions. * </p> * * <p> * What you should know about this particular trigger is that it is based on * org.quartz.CronTrigger, but the the functionality to build the sets from a * string are unused. Whereas CronTrigger would essentially deserialize by * rebuilding the TreeSets from the cronExpression, this class does not have a * cronExpression, and de/serializes the TreeSets in their entirety. This is * because the TreeSets map directly to the Struts user interface for set * selection, and no effort is made to write an interpreter to map them back * and forth between legacy UN*X cron expressions that CronTrigger uses. * </p> * * <p> * The method I use with this trigger is to instantiate it, then put it in the * ActionForm of a Struts bean, then let Struts manipulate it directly through * BeanUtils. You are by no means required to do that, but to fully understand * the concepts here, at least until there is better documentation, you should * understand how it works within that context first so you can write the * appropriate code that Struts does for you for free. I'll try to explain that * here. * </p> * * <p> * Struts JSP tags allow the user to use Apache BeanUtils to reference * components of beans by path. This is to say that a bean <code>Foo</code> * that has an accessor method <code>Bar getBar()</code> and given <code> * Bar</code> * has a primitive type <code>String</code> as a field named <code>splat</code>, * one can set the field to <i>"new string value"</i> as follows: * </p> * <code> * // create a new Foo with contained reference to a new Bar * Foo fooBean = new Foo(); * fooBean.setBar(new Bar()); * // set the splat string in the Bar bean from Foo * BeanUtils.setProperty(fooBean, "bar.splat", "new string value"); * </code> * <p> * In turn, Struts JSP tags use the bean addressing provided by BeanUtils to * address accessor methods within the bean graph that is rooted with the * ActionForm that is put into the Action context. * </p> * <p> * Finally, having all this allows you to put direct selection lists on the * screen of the UI, then map them directly into the UICronTrigger bean. Given * a ActionForm bean that was set up to contain a <code>UICronTrigger</code> * in a field called <code>trigger</code>, the following HTML code will * completely create your UI in Struts: * </p> * * <code> * <tr class="listRowUnshaded"> * <td width="80">Date</td> * <td align="right"> * <html:select property="trigger.daysOfWeek" size="5" multiple="true"> * <html:options property="trigger.daysOfWeekValues" labelProperty="trigger.daysOfWeekLabels"/> * </html:select> * <html:select property="trigger.daysOfMonth" size="5" multiple="true"> * <html:options property="trigger.daysOfMonthValues" labelProperty="trigger.daysOfMonthLabels"/> * </html:select> * <html:select property="trigger.months" size="5" multiple="true"> * <html:options property="trigger.monthsValues" labelProperty="trigger.monthsLabels"/> * </html:select> * <html:select property="trigger.years" size="5" multiple="true"> * <html:options property="trigger.yearsValues" labelProperty="trigger.yearsLabels"/> * </html:select> * </td> * </tr> * <tr class="listRowShaded"> * <td width="80">Time</td> * <td colspan="2" align="right"> * <html:select property="trigger.hours" size="5" multiple="true"> * <html:options property="trigger.hoursValues" labelProperty="trigger.hoursLabels"/> * </html:select> * <html:select property="trigger.minutes" size="5" multiple="true"> * <html:options property="trigger.minutesValues" labelProperty="trigger.minutesLabels"/> * </html:select> * </td> * </tr> * </code> * <p> * So if you don't want to use Struts, what you have to do is take the * information that was submitted on the form in the HTML select ranges, * iterate each of them, and add the values to the appropriate sets in the * fields of this class. Make sense? * </p> * * Note that this is not as versatile as the standard CronTrigger. There are * tricks with "last day of month" and repeating sets that need to be manually * selected, and sets that can happen for date ranges much longer than we can * reasonably map with direct selection in a UI. * * @see org.quartz.CronTrigger * @see Trigger * @see SimpleTrigger * * @author Brian Topping * @author based on code by Sharada Jambula, James House, Mads Henderson */public class UICronTrigger extends Trigger { /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constants. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** * <p> * Instructs the <code>{@link Scheduler}</code> that upon a mis-fire * situation, the <code>{@link org.quartz.CronTrigger}</code> wants to be * fired now by <code>Scheduler</code>. * </p> */ public static final int MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1; /** * <p> * Instructs the <code>{@link Scheduler}</code> that upon a mis-fire * situation, the <code>{@link org.quartz.CronTrigger}</code> wants to * have it's next-fire-time updated to the next time in the schedule after * the current time, but it does not to be fired now. * </p> */ public static final int MISFIRE_INSTRUCTION_DO_NOTHING = 2; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Data members. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ private static final int ALL_SPEC_INT = 99; // '*' private static final int NO_SPEC_INT = 98; // '?' private static final Integer ALL_SPEC = new Integer(ALL_SPEC_INT); private static final Integer NO_SPEC = new Integer(NO_SPEC_INT); private static Map monthMap = new HashMap(20); private static 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)); 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)); } private Date startTime = null; private Date endTime = null; private Date nextFireTime = null; private TimeZone timeZone = null; private Date previousFireTime = null; private TreeSet seconds = null; private TreeSet minutes = null; private TreeSet hours = null; private TreeSet daysOfMonth = null; private TreeSet months = null; private TreeSet daysOfWeek = null; private TreeSet years = null; private transient boolean lastdayOfWeek = false; private transient int nthdayOfWeek = 0; private transient boolean lastdayOfMonth = false; private transient boolean calendardayOfWeek = false; private transient boolean calendardayOfMonth = false; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constructors. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public void reset() { seconds = new TreeSet(); minutes = new TreeSet(); hours = new TreeSet(); daysOfMonth = new TreeSet(); months = new TreeSet(); daysOfWeek = new TreeSet(); years = new TreeSet(); // we always fire on the minute seconds.add(new Integer(0)); minutes.add(ALL_SPEC); for (int i = 0; i < 60; i++) minutes.add(new Integer(i)); hours.add(ALL_SPEC); for (int i = 0; i < 24; i++) hours.add(new Integer(i)); daysOfMonth.add(ALL_SPEC); for (int i = 1; i <= 31; i++) daysOfMonth.add(new Integer(i)); months.add(ALL_SPEC); for (int i = 1; i <= 12; i++) months.add(new Integer(i)); daysOfWeek.add(NO_SPEC); years.add(ALL_SPEC); for (int i = 1970; i <= 2099; i++) years.add(new Integer(i)); startTime = new Date(); setStartTime(startTime); setTimeZone(TimeZone.getDefault()); } /** * <p> * Create a <code>CronTrigger</code> with no settings. * </p> */ public UICronTrigger() { super(); reset(); } /** * <p> * Create a <code>CronTrigger</code> with the given name and group. * </p> */ public UICronTrigger(String name, String group) { super(name, group); reset(); } /** * <p> * Create a <code>CronTrigger</code> with the given name and group, and * associated with the identified <code>{@link Job}</code>. * </p> */ public UICronTrigger(String name, String group, String jobName, String jobGroup) { super(name, group, jobName, jobGroup); reset(); } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Interface. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** * <p> * Get the time at which the <code>CronTrigger</code> should occur. * </p> */ 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(); } /** * <p> * Get the time at which the <code>CronTrigger</code> should quit * repeating - even if repeastCount isn't yet satisfied. * </p> * * @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; } /** * <p> * Returns the next time at which the <code>CronTrigger</code> will fire. * If the trigger will not fire again, <code>null</code> will be * returned. The value returned is not guaranteed to be valid until after * the <code>Trigger</code> has been added to the scheduler. * </p> */ public Date getNextFireTime() { return this.nextFireTime; } public void updateAfterMisfire(org.quartz.Calendar cal) { int instr = getMisfireInstruction(); if (instr == MISFIRE_INSTRUCTION_SMART_POLICY) instr = MISFIRE_INSTRUCTION_DO_NOTHING; 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()); } } public Date getPreviousFireTime() { return this.previousFireTime; } /** * <p> * Set the previous time at which the <code>SimpleTrigger</code> fired. * </p> * * <p> * <b>This method should not be invoked by client code.</b> * </p> */ public void setPreviousFireTime(Date previousFireTime) { this.previousFireTime = previousFireTime; } /** * <p> * Sets the next time at which the <code>CronTrigger</code> will fire. If * the trigger will not fire again, <code>null</code> will be returned. * </p> */ public void setNextFireTime(Date nextFireTime) { this.nextFireTime = nextFireTime; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -