/* * 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 * under the License. * */ /* * Previously Copyright (c) 2001-2004 James House */ package org.quartz; import java.util.Date; import java.util.LinkedList; import org.quartz.utils.Key; /** *
* The base abstract class to be extended by all Triggers.
*
* Triggers s have a name and group associated with them, which
* should uniquely identify them within a single {@link Scheduler}.
*
* Triggers are the 'mechanism' by which Job s
* are scheduled. Many Trigger s can point to the same Job,
* but a single Trigger can only point to one Job.
*
* Triggers can 'send' parameters/data to Jobs by placing contents
* into the JobDataMap on the Trigger.
*
* Instructs the {@link Scheduler} that the {@link Trigger}
* has no further instructions.
*
* 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 the Job the
* abilitiy to 'see' anything placed in the context by its last execution).
*
* Instructs the {@link Scheduler} that the {@link Trigger}
* should be put in the COMPLETE state.
*
* Instructs the {@link Scheduler} that the {@link Trigger}
* wants itself deleted.
*
* Instructs the {@link Scheduler} that all Trigger
* s referencing the same {@link org.quartz.JobDetail} as
* this one should be put in the COMPLETE state.
*
* Instructs the {@link Scheduler} that all Trigger
* s referencing the same {@link org.quartz.JobDetail} as
* this one should be put in the ERROR state.
*
* Instructs the {@link Scheduler} that the Trigger
* should be put in the ERROR state.
*
* Instructs the {@link Scheduler} that upon a mis-fire
* situation, the updateAfterMisfire() method will be called
* on the Trigger to determine the mis-fire instruction.
*
* In order to see if this instruction fits your needs, you should look at
* the documentation for the getSmartMisfirePolicy() method
* on the particular Trigger implementation you are using.
*
* Indicates that the Trigger is in the "normal" state.
*
* Indicates that the Trigger is in the "paused" state.
*
* Indicates that the Trigger is in the "complete" state.
*
* "Complete" indicates that the trigger has not remaining fire-times in * its schedule. *
*/ public static final int STATE_COMPLETE = 2; /** *
* 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 the Job's
* class not existing in the classpath.
*
* When the trigger is in the error state, the scheduler will make no * attempts to fire it. *
*/ public static final int STATE_ERROR = 3; /** *
* Indicates that the Trigger is in the "blocked" state.
*
* A Trigger arrives at the blocked state when the job that
* it is associated with is a StatefulJob and it is
* currently executing.
*
* Indicates that the 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 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 Trigger
* 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 Trigger 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 Trigger.
*
* Set the name of this Trigger.
*
* Get the group of this Trigger.
*
* Set the name of this Trigger.
*
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 {@link org.quartz.JobDetail}.
*
* Set the name of the associated {@link org.quartz.JobDetail}.
*
* Get the name of the associated {@link org.quartz.JobDetail}'s
* group.
*
* Set the name of the associated {@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 Trigger in the format
* "group.name".
*
* Returns the 'full name' of the Job that the Trigger
* points to, in the format "group.name".
*
* Return the description given to the Trigger instance by
* its creator (if any).
*
* Set a description for the 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 Trigger should be persisted in the
* {@link org.quartz.spi.JobStore} for re-use after program
* restarts.
*
* Associate the {@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 {@link Calendar} associated with this
* Trigger.
*
null if there is no associated Calendar.
*/
public String getCalendarName() {
return calendarName;
}
/**
*
* 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 IllegalStateException.
*
* Set the JobDataMap to be associated with the
* Trigger.
*
* Whether or not the Trigger should be persisted in the
* {@link org.quartz.spi.JobStore} for re-use after program
* restarts.
*
* If not explicitly set, the default value is false.
*
true if the Trigger should be
* garbage collected along with the {@link Scheduler}.
*/
public boolean isVolatile() {
return volatility;
}
/**
* The priority of a Trigger acts as a tiebreaker such that if
* two Triggers 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 5.
*
Trigger acts as a tie breaker such that if
* two Triggers have the same scheduled fire time, then Quartz
* will do its best to give the one with the higher priority first access
* to a worker thread.
*
*
* If not explicitly set, the default value is 5.
*
* Add the specified name of a {@link TriggerListener} to
* the end of the Trigger's list of listeners.
*
* Remove the specified name of a {@link TriggerListener}
* from the Trigger's list of listeners.
*
* Returns an array of String containing the names of all
* {@link TriggerListener}s assigned to the Trigger,
* in the order in which they should be notified.
*
{@link TriggerListener}s from the Trigger.
*/
public void clearAllTriggerListeners() {
triggerListeners.clear();
}
/**
* * This method should not be used by the Quartz client. *
* *
* Called when the {@link Scheduler} has decided to 'fire'
* the trigger (execute the associated Job), in order to
* give the Trigger 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 the Trigger
* compute its first fire time, based on any associated calendar.
*
* After this method has been called, getNextFireTime()
* should return a valid answer.
*
Trigger will be fired
* by the scheduler, which is also the same value getNextFireTime()
* will return (until after the first firing of the Trigger).
*
*/
public abstract Date computeFirstFireTime(Calendar calendar);
/**
* * This method should not be used by the Quartz client. *
* *
* Called after the {@link Scheduler} has executed the
* {@link org.quartz.JobDetail} associated with the Trigger
* in order to get the final instruction code from the trigger.
*
JobExecutionContext that was used by the
* Job'sexecute(xx) method.
* @param result
* is the JobExecutionException 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 this Trigger to fire again.
*
* If the returned value is false then the Scheduler
* may remove the Trigger from the {@link org.quartz.spi.JobStore}.
*
* Get the time at which the Trigger should occur.
*
* The time at which the trigger's scheduling should start. May or may not * be the first actual fire time of the trigger, depending upon the type of * trigger and the settings of the other properties of the trigger. However * the first actual first time will not be before this date. *
** Setting a value in the past may cause a new trigger to compute a first * fire time that is in the past, which may cause an immediate misfire * of the trigger. *
*/ public abstract void setStartTime(Date startTime); public abstract void setEndTime(Date endTime); /** *
* Get the time at which the Trigger should quit repeating -
* even if an assigned 'repeatCount' isn't yet satisfied.
*
* Returns the next time at which the Trigger 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 Trigger
* has been added to the scheduler.
*
* Returns the previous time at which the Trigger fired.
* If the trigger has not yet fired, null will be returned.
*/
public abstract Date getPreviousFireTime();
/**
*
* Returns the next time at which the 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(); /** *
* Set the instruction the Scheduler should be given for
* handling misfire situations for this Trigger- the
* concrete Trigger type that you are using will have
* defined a set of additional MISFIRE_INSTRUCTION_XXX
* constants that may be passed to this method.
*
* If not explicitly set, the default value is MISFIRE_INSTRUCTION_SMART_POLICY.
*
* Get the instruction the Scheduler should be given for
* handling misfire situations for this Trigger- the
* concrete Trigger type that you are using will have
* defined a set of additional MISFIRE_INSTRUCTION_XXX
* constants that may be passed to this method.
*
* If not explicitly set, the default value is MISFIRE_INSTRUCTION_SMART_POLICY.
*
* This method should not be used by the Quartz client. *
* ** To be implemented by the concrete classes that extend this class. *
* *
* The implementation should update the Trigger's state
* based on the MISFIRE_INSTRUCTION_XXX that was selected when the Trigger
* was created.
*
* This method should not be used by the Quartz client. *
* ** To be implemented by the concrete class. *
* *
* The implementation should update the Trigger's state
* based on the given new version of the associated Calendar
* (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 a Scheduler.
*
* @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("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);
}
}
/**
*
* This method should not be used by the Quartz client. *
* *
* Usable by {@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. *
*/ public String getFireInstanceId() { return fireInstanceId; } /** ** 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(); } /** *
* Compare the next fire time of this Trigger to that of
* another.
*