Browse Source
Merge in CORE/base-third from ~ZHOUPING/base-third:feature/10.0 to feature/10.0 * commit '1737949fc3763fe6463629006677fbecdc80f6fa': REPORT-28620 10.0扫描后quartz有漏洞research/11.0
zhouping
5 years ago
7 changed files with 29 additions and 2487 deletions
@ -1,426 +0,0 @@
|
||||
/* |
||||
* Copyright 2001-2010 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. |
||||
* |
||||
*/ |
||||
|
||||
package com.fr.third.v2.org.quartz.plugins.xml; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.UnsupportedEncodingException; |
||||
import java.net.URL; |
||||
import java.net.URLDecoder; |
||||
import java.util.HashSet; |
||||
import java.util.Iterator; |
||||
import java.util.LinkedHashMap; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.StringTokenizer; |
||||
|
||||
import javax.transaction.UserTransaction; |
||||
|
||||
import com.fr.third.v2.org.quartz.JobDetail; |
||||
import com.fr.third.v2.org.quartz.Scheduler; |
||||
import com.fr.third.v2.org.quartz.SchedulerConfigException; |
||||
import com.fr.third.v2.org.quartz.SchedulerException; |
||||
import com.fr.third.v2.org.quartz.SimpleTrigger; |
||||
import com.fr.third.v2.org.quartz.plugins.SchedulerPluginWithUserTransactionSupport; |
||||
import com.fr.third.v2.org.quartz.JobBuilder; |
||||
import com.fr.third.v2.org.quartz.SimpleScheduleBuilder; |
||||
import com.fr.third.v2.org.quartz.TriggerBuilder; |
||||
import com.fr.third.v2.org.quartz.TriggerKey; |
||||
import com.fr.third.v2.org.quartz.jobs.FileScanJob; |
||||
import com.fr.third.v2.org.quartz.jobs.FileScanListener; |
||||
import com.fr.third.v2.org.quartz.xml.XMLSchedulingDataProcessor; |
||||
import com.fr.third.v2.org.quartz.spi.ClassLoadHelper; |
||||
|
||||
import static com.fr.third.v2.org.quartz.JobBuilder.newJob; |
||||
|
||||
/** |
||||
* This plugin loads XML file(s) to add jobs and schedule them with triggers |
||||
* as the scheduler is initialized, and can optionally periodically scan the |
||||
* file for changes. |
||||
* |
||||
* <p>The XML schema definition can be found here: |
||||
* http://www.quartz-scheduler.org/xml/job_scheduling_data_2_0.xsd</p>
|
||||
* |
||||
* <p> |
||||
* The periodically scanning of files for changes is not currently supported in a |
||||
* clustered environment. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If using this plugin with JobStoreCMT, be sure to set the |
||||
* plugin property <em>wrapInUserTransaction</em> to true. Also, if you have a |
||||
* positive <em>scanInterval</em> be sure to set |
||||
* <em>org.quartz.scheduler.wrapJobExecutionInUserTransaction</em> to true. |
||||
* </p> |
||||
* |
||||
* @see XMLSchedulingDataProcessor |
||||
* |
||||
* @author James House |
||||
* @author Pierre Awaragi |
||||
* @author pl47ypus |
||||
*/ |
||||
public class XMLSchedulingDataProcessorPlugin |
||||
extends SchedulerPluginWithUserTransactionSupport |
||||
implements FileScanListener { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
private static final int MAX_JOB_TRIGGER_NAME_LEN = 80; |
||||
private static final String JOB_INITIALIZATION_PLUGIN_NAME = "JobSchedulingDataLoaderPlugin"; |
||||
private static final String FILE_NAME_DELIMITERS = ","; |
||||
|
||||
private boolean failOnFileNotFound = true; |
||||
|
||||
private String fileNames = XMLSchedulingDataProcessor.QUARTZ_XML_DEFAULT_FILE_NAME; |
||||
|
||||
// Populated by initialization
|
||||
private Map<String, JobFile> jobFiles = new LinkedHashMap<String, JobFile>(); |
||||
|
||||
private long scanInterval = 0; |
||||
|
||||
boolean started = false; |
||||
|
||||
protected ClassLoadHelper classLoadHelper = null; |
||||
|
||||
private Set<String> jobTriggerNameSet = new HashSet<String>(); |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public XMLSchedulingDataProcessorPlugin() { |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* Comma separated list of file names (with paths) to the XML files that should be read. |
||||
*/ |
||||
public String getFileNames() { |
||||
return fileNames; |
||||
} |
||||
|
||||
/** |
||||
* The file name (and path) to the XML file that should be read. |
||||
*/ |
||||
public void setFileNames(String fileNames) { |
||||
this.fileNames = fileNames; |
||||
} |
||||
|
||||
/** |
||||
* The interval (in seconds) at which to scan for changes to the file. |
||||
* If the file has been changed, it is re-loaded and parsed. The default |
||||
* value for the interval is 0, which disables scanning. |
||||
* |
||||
* @return Returns the scanInterval. |
||||
*/ |
||||
public long getScanInterval() { |
||||
return scanInterval / 1000; |
||||
} |
||||
|
||||
/** |
||||
* The interval (in seconds) at which to scan for changes to the file. |
||||
* If the file has been changed, it is re-loaded and parsed. The default |
||||
* value for the interval is 0, which disables scanning. |
||||
* |
||||
* @param scanInterval The scanInterval to set. |
||||
*/ |
||||
public void setScanInterval(long scanInterval) { |
||||
this.scanInterval = scanInterval * 1000; |
||||
} |
||||
|
||||
/** |
||||
* Whether or not initialization of the plugin should fail (throw an |
||||
* exception) if the file cannot be found. Default is <code>true</code>. |
||||
*/ |
||||
public boolean isFailOnFileNotFound() { |
||||
return failOnFileNotFound; |
||||
} |
||||
|
||||
/** |
||||
* Whether or not initialization of the plugin should fail (throw an |
||||
* exception) if the file cannot be found. Default is <code>true</code>. |
||||
*/ |
||||
public void setFailOnFileNotFound(boolean failOnFileNotFound) { |
||||
this.failOnFileNotFound = failOnFileNotFound; |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* SchedulerPlugin Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Called during creation of the <code>Scheduler</code> in order to give |
||||
* the <code>SchedulerPlugin</code> a chance to initialize. |
||||
* </p> |
||||
* |
||||
* @throws SchedulerConfigException |
||||
* if there is an error initializing. |
||||
*/ |
||||
public void initialize(String name, final Scheduler scheduler, ClassLoadHelper schedulerFactoryClassLoadHelper) |
||||
throws SchedulerException { |
||||
super.initialize(name, scheduler); |
||||
this.classLoadHelper = schedulerFactoryClassLoadHelper; |
||||
|
||||
getLog().info("Registering Quartz Job Initialization Plug-in."); |
||||
|
||||
// Create JobFile objects
|
||||
StringTokenizer stok = new StringTokenizer(fileNames, FILE_NAME_DELIMITERS); |
||||
while (stok.hasMoreTokens()) { |
||||
final String fileName = stok.nextToken(); |
||||
final JobFile jobFile = new JobFile(fileName); |
||||
jobFiles.put(fileName, jobFile); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void start(UserTransaction userTransaction) { |
||||
try { |
||||
if (jobFiles.isEmpty() == false) { |
||||
|
||||
if (scanInterval > 0) { |
||||
getScheduler().getContext().put(JOB_INITIALIZATION_PLUGIN_NAME + '_' + getName(), this); |
||||
} |
||||
|
||||
Iterator<JobFile> iterator = jobFiles.values().iterator(); |
||||
while (iterator.hasNext()) { |
||||
JobFile jobFile = iterator.next(); |
||||
|
||||
if (scanInterval > 0) { |
||||
String jobTriggerName = buildJobTriggerName(jobFile.getFileBasename()); |
||||
TriggerKey tKey = new TriggerKey(jobTriggerName, JOB_INITIALIZATION_PLUGIN_NAME); |
||||
|
||||
// remove pre-existing job/trigger, if any
|
||||
getScheduler().unscheduleJob(tKey); |
||||
|
||||
JobDetail job = JobBuilder.newJob().withIdentity(jobTriggerName, JOB_INITIALIZATION_PLUGIN_NAME).ofType(FileScanJob.class) |
||||
.usingJobData(FileScanJob.FILE_NAME, jobFile.getFileName()) |
||||
.usingJobData(FileScanJob.FILE_SCAN_LISTENER_NAME, JOB_INITIALIZATION_PLUGIN_NAME + '_' + getName()) |
||||
.build(); |
||||
|
||||
SimpleTrigger trig = TriggerBuilder.newTrigger().withIdentity(tKey).withSchedule( |
||||
SimpleScheduleBuilder.simpleSchedule().repeatForever().withIntervalInMilliseconds(scanInterval)) |
||||
.forJob(job) |
||||
.build(); |
||||
|
||||
getScheduler().scheduleJob(job, trig); |
||||
getLog().debug("Scheduled file scan job for data file: {}, at interval: {}", jobFile.getFileName(), scanInterval); |
||||
} |
||||
|
||||
processFile(jobFile); |
||||
} |
||||
} |
||||
} catch(SchedulerException se) { |
||||
getLog().error("Error starting background-task for watching jobs file.", se); |
||||
} finally { |
||||
started = true; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Helper method for generating unique job/trigger name for the |
||||
* file scanning jobs (one per FileJob). The unique names are saved |
||||
* in jobTriggerNameSet. |
||||
*/ |
||||
private String buildJobTriggerName( |
||||
String fileBasename) { |
||||
// Name w/o collisions will be prefix + _ + filename (with '.' of filename replaced with '_')
|
||||
// For example: JobInitializationPlugin_jobInitializer_myjobs_xml
|
||||
String jobTriggerName = JOB_INITIALIZATION_PLUGIN_NAME + '_' + getName() + '_' + fileBasename.replace('.', '_'); |
||||
|
||||
// If name is too long (DB column is 80 chars), then truncate to max length
|
||||
if (jobTriggerName.length() > MAX_JOB_TRIGGER_NAME_LEN) { |
||||
jobTriggerName = jobTriggerName.substring(0, MAX_JOB_TRIGGER_NAME_LEN); |
||||
} |
||||
|
||||
// Make sure this name is unique in case the same file name under different
|
||||
// directories is being checked, or had a naming collision due to length truncation.
|
||||
// If there is a conflict, keep incrementing a _# suffix on the name (being sure
|
||||
// not to get too long), until we find a unique name.
|
||||
int currentIndex = 1; |
||||
while (jobTriggerNameSet.add(jobTriggerName) == false) { |
||||
// If not our first time through, then strip off old numeric suffix
|
||||
if (currentIndex > 1) { |
||||
jobTriggerName = jobTriggerName.substring(0, jobTriggerName.lastIndexOf('_')); |
||||
} |
||||
|
||||
String numericSuffix = "_" + currentIndex++; |
||||
|
||||
// If the numeric suffix would make the name too long, then make room for it.
|
||||
if (jobTriggerName.length() > (MAX_JOB_TRIGGER_NAME_LEN - numericSuffix.length())) { |
||||
jobTriggerName = jobTriggerName.substring(0, (MAX_JOB_TRIGGER_NAME_LEN - numericSuffix.length())); |
||||
} |
||||
|
||||
jobTriggerName += numericSuffix; |
||||
} |
||||
|
||||
return jobTriggerName; |
||||
} |
||||
|
||||
/** |
||||
* Overriden to ignore <em>wrapInUserTransaction</em> because shutdown() |
||||
* does not interact with the <code>Scheduler</code>. |
||||
*/ |
||||
@Override |
||||
public void shutdown() { |
||||
// Since we have nothing to do, override base shutdown so don't
|
||||
// get extranious UserTransactions.
|
||||
} |
||||
|
||||
private void processFile(JobFile jobFile) { |
||||
if (jobFile == null || !jobFile.getFileFound()) { |
||||
return; |
||||
} |
||||
|
||||
|
||||
try { |
||||
XMLSchedulingDataProcessor processor = |
||||
new XMLSchedulingDataProcessor(this.classLoadHelper); |
||||
|
||||
processor.addJobGroupToNeverDelete(JOB_INITIALIZATION_PLUGIN_NAME); |
||||
processor.addTriggerGroupToNeverDelete(JOB_INITIALIZATION_PLUGIN_NAME); |
||||
|
||||
processor.processFileAndScheduleJobs( |
||||
jobFile.getFileName(), |
||||
jobFile.getFileName(), // systemId
|
||||
getScheduler()); |
||||
} catch (Exception e) { |
||||
getLog().error("Error scheduling jobs: " + e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
public void processFile(String filePath) { |
||||
processFile((JobFile)jobFiles.get(filePath)); |
||||
} |
||||
|
||||
/** |
||||
* @see FileScanListener#fileUpdated(java.lang.String) |
||||
*/ |
||||
public void fileUpdated(String fileName) { |
||||
if (started) { |
||||
processFile(fileName); |
||||
} |
||||
} |
||||
|
||||
class JobFile { |
||||
private String fileName; |
||||
|
||||
// These are set by initialize()
|
||||
private String filePath; |
||||
private String fileBasename; |
||||
private boolean fileFound; |
||||
|
||||
protected JobFile(String fileName) throws SchedulerException { |
||||
this.fileName = fileName; |
||||
initialize(); |
||||
} |
||||
|
||||
protected String getFileName() { |
||||
return fileName; |
||||
} |
||||
|
||||
protected boolean getFileFound() { |
||||
return fileFound; |
||||
} |
||||
|
||||
protected String getFilePath() { |
||||
return filePath; |
||||
} |
||||
|
||||
protected String getFileBasename() { |
||||
return fileBasename; |
||||
} |
||||
|
||||
private void initialize() throws SchedulerException { |
||||
InputStream f = null; |
||||
try { |
||||
String furl = null; |
||||
|
||||
File file = new File(getFileName()); // files in filesystem
|
||||
if (!file.exists()) { |
||||
URL url = classLoadHelper.getResource(getFileName()); |
||||
if(url != null) { |
||||
try { |
||||
furl = URLDecoder.decode(url.getPath(), "UTF-8"); |
||||
} catch (UnsupportedEncodingException e) { |
||||
furl = url.getPath(); |
||||
} |
||||
file = new File(furl); |
||||
try { |
||||
f = url.openStream(); |
||||
} catch (IOException ignor) { |
||||
// Swallow the exception
|
||||
} |
||||
} |
||||
} else { |
||||
try { |
||||
f = new java.io.FileInputStream(file); |
||||
}catch (FileNotFoundException e) { |
||||
// ignore
|
||||
} |
||||
} |
||||
|
||||
if (f == null) { |
||||
if (isFailOnFileNotFound()) { |
||||
throw new SchedulerException( |
||||
"File named '" + getFileName() + "' does not exist."); |
||||
} else { |
||||
getLog().warn("File named '" + getFileName() + "' does not exist."); |
||||
} |
||||
} else { |
||||
fileFound = true; |
||||
} |
||||
filePath = (furl != null) ? furl : file.getAbsolutePath(); |
||||
fileBasename = file.getName(); |
||||
} finally { |
||||
try { |
||||
if (f != null) { |
||||
f.close(); |
||||
} |
||||
} catch (IOException ioe) { |
||||
getLog().warn("Error closing jobs file " + getFileName(), ioe); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -1,144 +0,0 @@
|
||||
/* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
package com.fr.third.v2.org.quartz.xml; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* Reports JobSchedulingDataLoader validation exceptions. |
||||
* |
||||
* @author <a href="mailto:bonhamcm@thirdeyeconsulting.com">Chris Bonham</a> |
||||
*/ |
||||
public class ValidationException extends Exception { |
||||
|
||||
private static final long serialVersionUID = -1697832087051681357L; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private Collection<Exception> validationExceptions = new ArrayList<Exception>(); |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* Constructor for ValidationException. |
||||
*/ |
||||
public ValidationException() { |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* Constructor for ValidationException. |
||||
* |
||||
* @param message |
||||
* exception message. |
||||
*/ |
||||
public ValidationException(String message) { |
||||
super(message); |
||||
} |
||||
|
||||
/** |
||||
* Constructor for ValidationException. |
||||
* |
||||
* @param errors |
||||
* collection of validation exceptions. |
||||
*/ |
||||
public ValidationException(Collection<Exception> errors) { |
||||
this(); |
||||
this.validationExceptions = Collections |
||||
.unmodifiableCollection(validationExceptions); |
||||
initCause(errors.iterator().next()); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Constructor for ValidationException. |
||||
* |
||||
* @param message |
||||
* exception message. |
||||
* @param errors |
||||
* collection of validation exceptions. |
||||
*/ |
||||
public ValidationException(String message, Collection<Exception> errors) { |
||||
this(message); |
||||
this.validationExceptions = Collections |
||||
.unmodifiableCollection(validationExceptions); |
||||
initCause(errors.iterator().next()); |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* Returns collection of errors. |
||||
* |
||||
* @return collection of errors. |
||||
*/ |
||||
public Collection<Exception> getValidationExceptions() { |
||||
return validationExceptions; |
||||
} |
||||
|
||||
/** |
||||
* Returns the detail message string. |
||||
* |
||||
* @return the detail message string. |
||||
*/ |
||||
@Override |
||||
public String getMessage() { |
||||
if (getValidationExceptions().size() == 0) { return super.getMessage(); } |
||||
|
||||
StringBuffer sb = new StringBuffer(); |
||||
|
||||
boolean first = true; |
||||
|
||||
for (Iterator<Exception> iter = getValidationExceptions().iterator(); iter |
||||
.hasNext(); ) { |
||||
Exception e = iter.next(); |
||||
|
||||
if (!first) { |
||||
sb.append('\n'); |
||||
first = false; |
||||
} |
||||
|
||||
sb.append(e.getMessage()); |
||||
} |
||||
|
||||
return sb.toString(); |
||||
} |
||||
|
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,339 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" |
||||
xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData" |
||||
targetNamespace="http://www.quartz-scheduler.org/xml/JobSchedulingData" |
||||
elementFormDefault="qualified" |
||||
version="1.8"> |
||||
|
||||
<xs:element name="job-scheduling-data"> |
||||
<xs:annotation> |
||||
<xs:documentation>Root level node</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:complexType> |
||||
<xs:sequence maxOccurs="unbounded"> |
||||
<xs:element name="pre-processing-commands" type="pre-processing-commandsType" minOccurs="0" maxOccurs="1"> |
||||
<xs:annotation> |
||||
<xs:documentation>Commands to be executed before scheduling the jobs and triggers in this file.</xs:documentation> |
||||
</xs:annotation> |
||||
</xs:element> |
||||
<xs:element name="processing-directives" type="processing-directivesType" minOccurs="0" maxOccurs="1"> |
||||
<xs:annotation> |
||||
<xs:documentation>Directives to be followed while scheduling the jobs and triggers in this file.</xs:documentation> |
||||
</xs:annotation> |
||||
</xs:element> |
||||
<xs:element name="schedule" minOccurs="0" maxOccurs="unbounded"> |
||||
<xs:complexType> |
||||
<xs:sequence maxOccurs="unbounded"> |
||||
<xs:element name="job" type="job-detailType" minOccurs="0" maxOccurs="unbounded"/> |
||||
<xs:element name="trigger" type="triggerType" minOccurs="0" maxOccurs="unbounded"/> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
</xs:element> |
||||
</xs:sequence> |
||||
<xs:attribute name="version" type="xs:string"> |
||||
<xs:annotation> |
||||
<xs:documentation>Version of the XML Schema instance</xs:documentation> |
||||
</xs:annotation> |
||||
</xs:attribute> |
||||
</xs:complexType> |
||||
</xs:element> |
||||
|
||||
<xs:complexType name="pre-processing-commandsType"> |
||||
<xs:sequence maxOccurs="unbounded"> |
||||
<xs:element name="delete-jobs-in-group" type="xs:string" minOccurs="0" maxOccurs="unbounded"> |
||||
<xs:annotation><xs:documentation>Delete all jobs, if any, in the identified group. "*" can be used to identify all groups. Will also result in deleting all triggers related to the jobs.</xs:documentation></xs:annotation> |
||||
</xs:element> |
||||
<xs:element name="delete-triggers-in-group" type="xs:string" minOccurs="0" maxOccurs="unbounded"> |
||||
<xs:annotation><xs:documentation>Delete all triggers, if any, in the identified group. "*" can be used to identify all groups. Will also result in deletion of related jobs that are non-durable.</xs:documentation></xs:annotation> |
||||
</xs:element> |
||||
<xs:element name="delete-job" minOccurs="0" maxOccurs="unbounded"> |
||||
<xs:annotation><xs:documentation>Delete the identified job if it exists (will also result in deleting all triggers related to it).</xs:documentation></xs:annotation> |
||||
<xs:complexType> |
||||
<xs:sequence> |
||||
<xs:element name="name" type="xs:string"/> |
||||
<xs:element name="group" type="xs:string" minOccurs="0"/> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
</xs:element> |
||||
<xs:element name="delete-trigger" minOccurs="0" maxOccurs="unbounded"> |
||||
<xs:annotation><xs:documentation>Delete the identified trigger if it exists (will also result in deletion of related jobs that are non-durable).</xs:documentation></xs:annotation> |
||||
<xs:complexType> |
||||
<xs:sequence> |
||||
<xs:element name="name" type="xs:string"/> |
||||
<xs:element name="group" type="xs:string" minOccurs="0"/> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
</xs:element> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="processing-directivesType"> |
||||
<xs:sequence> |
||||
<xs:element name="overwrite-existing-data" type="xs:boolean" minOccurs="0" default="true"> |
||||
<xs:annotation><xs:documentation>Whether the existing scheduling data (with same identifiers) will be overwritten. If false, and ignore-duplicates is not false, and jobs or triggers with the same names already exist as those in the file, an error will occur.</xs:documentation></xs:annotation> |
||||
</xs:element> |
||||
<xs:element name="ignore-duplicates" type="xs:boolean" minOccurs="0" default="false"> |
||||
<xs:annotation><xs:documentation>If true (and overwrite-existing-data is false) then any job/triggers encountered in this file that have names that already exist in the scheduler will be ignored, and no error will be produced.</xs:documentation></xs:annotation> |
||||
</xs:element> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="job-detailType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a JobDetail</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:sequence> |
||||
<xs:element name="name" type="xs:string"/> |
||||
<xs:element name="group" type="xs:string" minOccurs="0"/> |
||||
<xs:element name="description" type="xs:string" minOccurs="0"/> |
||||
<xs:element name="job-class" type="xs:string"/> |
||||
<xs:element name="job-listener-ref" type="xs:string" minOccurs="0"/> |
||||
<xs:sequence minOccurs="0"> |
||||
<xs:element name="volatility" type="xs:boolean"/> |
||||
<xs:element name="durability" type="xs:boolean"/> |
||||
<xs:element name="recover" type="xs:boolean"/> |
||||
</xs:sequence> |
||||
<xs:element name="job-data-map" type="job-data-mapType" minOccurs="0"/> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="job-data-mapType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a JobDataMap</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:sequence minOccurs="0" maxOccurs="unbounded"> |
||||
<xs:element name="entry" type="entryType"/> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="entryType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a JobDataMap entry</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:sequence> |
||||
<xs:element name="key" type="xs:string"/> |
||||
<xs:element name="value" type="xs:string"/> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="triggerType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a Trigger</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:choice> |
||||
<xs:element name="simple" type="simpleTriggerType"/> |
||||
<xs:element name="cron" type="cronTriggerType"/> |
||||
<xs:element name="date-interval" type="dateIntervalTriggerType"/> |
||||
</xs:choice> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="abstractTriggerType" abstract="true"> |
||||
<xs:annotation> |
||||
<xs:documentation>Common Trigger definitions</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:sequence> |
||||
<xs:element name="name" type="xs:string"/> |
||||
<xs:element name="group" type="xs:string" minOccurs="0"/> |
||||
<xs:element name="description" type="xs:string" minOccurs="0"/> |
||||
<xs:element name="job-name" type="xs:string"/> |
||||
<xs:element name="job-group" type="xs:string" minOccurs="0"/> |
||||
<xs:element name="calendar-name" type="xs:string" minOccurs="0"/> |
||||
<xs:element name="volatility" type="xs:boolean" minOccurs="0"/> |
||||
<xs:element name="job-data-map" type="job-data-mapType" minOccurs="0"/> |
||||
<xs:sequence minOccurs="0"> |
||||
<xs:element name="start-time" type="xs:dateTime"/> |
||||
<xs:element name="end-time" type="xs:dateTime" minOccurs="0"/> |
||||
</xs:sequence> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="simpleTriggerType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a SimpleTrigger</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:complexContent> |
||||
<xs:extension base="abstractTriggerType"> |
||||
<xs:sequence> |
||||
<xs:element name="misfire-instruction" type="simple-trigger-misfire-instructionType" minOccurs="0" /> |
||||
<xs:sequence minOccurs="0"> |
||||
<xs:element name="repeat-count" type="repeat-countType"/> |
||||
<xs:element name="repeat-interval" type="xs:nonNegativeInteger"/> |
||||
</xs:sequence> |
||||
</xs:sequence> |
||||
</xs:extension> |
||||
</xs:complexContent> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="cronTriggerType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a CronTrigger</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:complexContent> |
||||
<xs:extension base="abstractTriggerType"> |
||||
<xs:sequence> |
||||
<xs:element name="misfire-instruction" type="cron-trigger-misfire-instructionType" minOccurs="0"/> |
||||
<xs:element name="cron-expression" type="cron-expressionType"/> |
||||
<xs:element name="time-zone" type="xs:string" minOccurs="0"/> |
||||
</xs:sequence> |
||||
</xs:extension> |
||||
</xs:complexContent> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="dateIntervalTriggerType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a DateIntervalTrigger</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:complexContent> |
||||
<xs:extension base="abstractTriggerType"> |
||||
<xs:sequence> |
||||
<xs:element name="misfire-instruction" type="date-interval-trigger-misfire-instructionType" minOccurs="0"/> |
||||
<xs:element name="repeat-interval" type="xs:nonNegativeInteger"/> |
||||
<xs:element name="repeat-interval-unit" type="interval-unitType"/> |
||||
</xs:sequence> |
||||
</xs:extension> |
||||
</xs:complexContent> |
||||
</xs:complexType> |
||||
|
||||
<xs:simpleType name="cron-expressionType"> |
||||
<xs:annotation> |
||||
<xs:documentation> |
||||
Cron expression (see JavaDoc for examples) |
||||
|
||||
Special thanks to Chris Thatcher (thatcher@butterfly.net) for the regular expression! |
||||
|
||||
Regular expressions are not my strong point but I believe this is complete, |
||||
with the caveat that order for expressions like 3-0 is not legal but will pass, |
||||
and month and day names must be capitalized. |
||||
If you want to examine the correctness look for the [\s] to denote the |
||||
seperation of individual regular expressions. This is how I break them up visually |
||||
to examine them: |
||||
|
||||
SECONDS: |
||||
( |
||||
((([0-9]|[0-5][0-9]),)*([0-9]|[0-5][0-9])) |
||||
| (([\*]|[0-9]|[0-5][0-9])(/|-)([0-9]|[0-5][0-9])) |
||||
| ([\?]) |
||||
| ([\*]) |
||||
) [\s] |
||||
MINUTES: |
||||
( |
||||
((([0-9]|[0-5][0-9]),)*([0-9]|[0-5][0-9])) |
||||
| (([\*]|[0-9]|[0-5][0-9])(/|-)([0-9]|[0-5][0-9])) |
||||
| ([\?]) |
||||
| ([\*]) |
||||
) [\s] |
||||
HOURS: |
||||
( |
||||
((([0-9]|[0-1][0-9]|[2][0-3]),)*([0-9]|[0-1][0-9]|[2][0-3])) |
||||
| (([\*]|[0-9]|[0-1][0-9]|[2][0-3])(/|-)([0-9]|[0-1][0-9]|[2][0-3])) |
||||
| ([\?]) |
||||
| ([\*]) |
||||
) [\s] |
||||
DAY OF MONTH: |
||||
( |
||||
((([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]),)*([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(C)?) |
||||
| (([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(/|-)([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(C)?) |
||||
| (L) |
||||
| (LW) |
||||
| ([1-9]W) |
||||
| ([1-3][0-9]W) |
||||
| ([\?]) |
||||
| ([\*]) |
||||
)[\s] |
||||
MONTH: |
||||
( |
||||
((([1-9]|0[1-9]|1[0-2]),)*([1-9]|0[1-9]|1[0-2])) |
||||
| (([1-9]|0[1-9]|1[0-2])(/|-)([1-9]|0[1-9]|1[0-2])) |
||||
| (((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC),)*(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)) |
||||
| ((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-|/)(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)) |
||||
| ([\?]) |
||||
| ([\*]) |
||||
)[\s] |
||||
DAY OF WEEK: |
||||
( |
||||
(([1-7],)*([1-7])) |
||||
| ([1-7](/|-)([1-7])) |
||||
| (((MON|TUE|WED|THU|FRI|SAT|SUN),)*(MON|TUE|WED|THU|FRI|SAT|SUN)(C)?) |
||||
| ((MON|TUE|WED|THU|FRI|SAT|SUN)(-|/)(MON|TUE|WED|THU|FRI|SAT|SUN)(C)?) |
||||
| (([1-7]|(MON|TUE|WED|THU|FRI|SAT|SUN))(L|LW)?) |
||||
| (([1-7]|MON|TUE|WED|THU|FRI|SAT|SUN)#([1-7])?) |
||||
| ([\?]) |
||||
| ([\*]) |
||||
) |
||||
YEAR (OPTIONAL): |
||||
( |
||||
[\s]? |
||||
([\*])? |
||||
| ((19[7-9][0-9])|(20[0-9][0-9]))? |
||||
| (((19[7-9][0-9])|(20[0-9][0-9]))(-|/)((19[7-9][0-9])|(20[0-9][0-9])))? |
||||
| ((((19[7-9][0-9])|(20[0-9][0-9])),)*((19[7-9][0-9])|(20[0-9][0-9])))? |
||||
) |
||||
</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:restriction base="xs:string"> |
||||
<xs:pattern value="(((([0-9]|[0-5][0-9]),)*([0-9]|[0-5][0-9]))|(([\*]|[0-9]|[0-5][0-9])(/|-)([0-9]|[0-5][0-9]))|([\?])|([\*]))[\s](((([0-9]|[0-5][0-9]),)*([0-9]|[0-5][0-9]))|(([\*]|[0-9]|[0-5][0-9])(/|-)([0-9]|[0-5][0-9]))|([\?])|([\*]))[\s](((([0-9]|[0-1][0-9]|[2][0-3]),)*([0-9]|[0-1][0-9]|[2][0-3]))|(([\*]|[0-9]|[0-1][0-9]|[2][0-3])(/|-)([0-9]|[0-1][0-9]|[2][0-3]))|([\?])|([\*]))[\s](((([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]),)*([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(C)?)|(([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(/|-)([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(C)?)|(L)|(LW)|([1-9]W)|([1-3][0-9]W)|([\?])|([\*]))[\s](((([1-9]|0[1-9]|1[0-2]),)*([1-9]|0[1-9]|1[0-2]))|(([1-9]|0[1-9]|1[0-2])(/|-)([1-9]|0[1-9]|1[0-2]))|(((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC),)*(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))|((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-|/)(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))|([\?])|([\*]))[\s]((([1-7],)*([1-7]))|([1-7](/|-)([1-7]))|(((MON|TUE|WED|THU|FRI|SAT|SUN),)*(MON|TUE|WED|THU|FRI|SAT|SUN)(C)?)|((MON|TUE|WED|THU|FRI|SAT|SUN)(-|/)(MON|TUE|WED|THU|FRI|SAT|SUN)(C)?)|(([1-7]|(MON|TUE|WED|THU|FRI|SAT|SUN))?(L|LW)?)|(([1-7]|MON|TUE|WED|THU|FRI|SAT|SUN)#([1-7])?)|([\?])|([\*]))([\s]?(([\*])?|(19[7-9][0-9])|(20[0-9][0-9]))?| (((19[7-9][0-9])|(20[0-9][0-9]))(-|/)((19[7-9][0-9])|(20[0-9][0-9])))?| ((((19[7-9][0-9])|(20[0-9][0-9])),)*((19[7-9][0-9])|(20[0-9][0-9])))?)"/> |
||||
</xs:restriction> |
||||
</xs:simpleType> |
||||
|
||||
<xs:simpleType name="repeat-countType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Number of times to repeat the Trigger (-1 for indefinite)</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:restriction base="xs:integer"> |
||||
<xs:minInclusive value="-1"/> |
||||
</xs:restriction> |
||||
</xs:simpleType> |
||||
|
||||
|
||||
<xs:simpleType name="simple-trigger-misfire-instructionType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Simple Trigger Misfire Instructions</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:restriction base="xs:string"> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_SMART_POLICY"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_FIRE_NOW"/> |
||||
</xs:restriction> |
||||
</xs:simpleType> |
||||
|
||||
<xs:simpleType name="cron-trigger-misfire-instructionType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Simple Trigger Misfire Instructions</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:restriction base="xs:string"> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_SMART_POLICY"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_DO_NOTHING"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_FIRE_ONCE_NOW"/> |
||||
</xs:restriction> |
||||
</xs:simpleType> |
||||
|
||||
<xs:simpleType name="date-interval-trigger-misfire-instructionType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Date Interval Trigger Misfire Instructions</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:restriction base="xs:string"> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_SMART_POLICY"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_DO_NOTHING"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_FIRE_ONCE_NOW"/> |
||||
</xs:restriction> |
||||
</xs:simpleType> |
||||
|
||||
<xs:simpleType name="interval-unitType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Interval Units</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:restriction base="xs:string"> |
||||
<xs:pattern value="DAY"/> |
||||
<xs:pattern value="HOUR"/> |
||||
<xs:pattern value="MINUTE"/> |
||||
<xs:pattern value="MONTH"/> |
||||
<xs:pattern value="SECOND"/> |
||||
<xs:pattern value="WEEK"/> |
||||
<xs:pattern value="YEAR"/> |
||||
</xs:restriction> |
||||
</xs:simpleType> |
||||
|
||||
</xs:schema> |
@ -1,342 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" |
||||
xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData" |
||||
targetNamespace="http://www.quartz-scheduler.org/xml/JobSchedulingData" |
||||
elementFormDefault="qualified" |
||||
version="2.0"> |
||||
|
||||
<xs:element name="job-scheduling-data"> |
||||
<xs:annotation> |
||||
<xs:documentation>Root level node</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:complexType> |
||||
<xs:sequence maxOccurs="unbounded"> |
||||
<xs:element name="pre-processing-commands" type="pre-processing-commandsType" minOccurs="0" maxOccurs="1"> |
||||
<xs:annotation> |
||||
<xs:documentation>Commands to be executed before scheduling the jobs and triggers in this file.</xs:documentation> |
||||
</xs:annotation> |
||||
</xs:element> |
||||
<xs:element name="processing-directives" type="processing-directivesType" minOccurs="0" maxOccurs="1"> |
||||
<xs:annotation> |
||||
<xs:documentation>Directives to be followed while scheduling the jobs and triggers in this file.</xs:documentation> |
||||
</xs:annotation> |
||||
</xs:element> |
||||
<xs:element name="schedule" minOccurs="0" maxOccurs="unbounded"> |
||||
<xs:complexType> |
||||
<xs:sequence maxOccurs="unbounded"> |
||||
<xs:element name="job" type="job-detailType" minOccurs="0" maxOccurs="unbounded"/> |
||||
<xs:element name="trigger" type="triggerType" minOccurs="0" maxOccurs="unbounded"/> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
</xs:element> |
||||
</xs:sequence> |
||||
<xs:attribute name="version" type="xs:string"> |
||||
<xs:annotation> |
||||
<xs:documentation>Version of the XML Schema instance</xs:documentation> |
||||
</xs:annotation> |
||||
</xs:attribute> |
||||
</xs:complexType> |
||||
</xs:element> |
||||
|
||||
<xs:complexType name="pre-processing-commandsType"> |
||||
<xs:sequence maxOccurs="unbounded"> |
||||
<xs:element name="delete-jobs-in-group" type="xs:string" minOccurs="0" maxOccurs="unbounded"> |
||||
<xs:annotation><xs:documentation>Delete all jobs, if any, in the identified group. "*" can be used to identify all groups. Will also result in deleting all triggers related to the jobs.</xs:documentation></xs:annotation> |
||||
</xs:element> |
||||
<xs:element name="delete-triggers-in-group" type="xs:string" minOccurs="0" maxOccurs="unbounded"> |
||||
<xs:annotation><xs:documentation>Delete all triggers, if any, in the identified group. "*" can be used to identify all groups. Will also result in deletion of related jobs that are non-durable.</xs:documentation></xs:annotation> |
||||
</xs:element> |
||||
<xs:element name="delete-job" minOccurs="0" maxOccurs="unbounded"> |
||||
<xs:annotation><xs:documentation>Delete the identified job if it exists (will also result in deleting all triggers related to it).</xs:documentation></xs:annotation> |
||||
<xs:complexType> |
||||
<xs:sequence> |
||||
<xs:element name="name" type="xs:string"/> |
||||
<xs:element name="group" type="xs:string" minOccurs="0"/> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
</xs:element> |
||||
<xs:element name="delete-trigger" minOccurs="0" maxOccurs="unbounded"> |
||||
<xs:annotation><xs:documentation>Delete the identified trigger if it exists (will also result in deletion of related jobs that are non-durable).</xs:documentation></xs:annotation> |
||||
<xs:complexType> |
||||
<xs:sequence> |
||||
<xs:element name="name" type="xs:string"/> |
||||
<xs:element name="group" type="xs:string" minOccurs="0"/> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
</xs:element> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="processing-directivesType"> |
||||
<xs:sequence> |
||||
<xs:element name="overwrite-existing-data" type="xs:boolean" minOccurs="0" default="true"> |
||||
<xs:annotation><xs:documentation>Whether the existing scheduling data (with same identifiers) will be overwritten. If false, and ignore-duplicates is not false, and jobs or triggers with the same names already exist as those in the file, an error will occur.</xs:documentation></xs:annotation> |
||||
</xs:element> |
||||
<xs:element name="ignore-duplicates" type="xs:boolean" minOccurs="0" default="false"> |
||||
<xs:annotation><xs:documentation>If true (and overwrite-existing-data is false) then any job/triggers encountered in this file that have names that already exist in the scheduler will be ignored, and no error will be produced.</xs:documentation></xs:annotation> |
||||
</xs:element> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="job-detailType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a JobDetail</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:sequence> |
||||
<xs:element name="name" type="xs:string"/> |
||||
<xs:element name="group" type="xs:string" minOccurs="0"/> |
||||
<xs:element name="description" type="xs:string" minOccurs="0"/> |
||||
<xs:element name="job-class" type="xs:string"/> |
||||
<xs:sequence minOccurs="0"> |
||||
<xs:element name="durability" type="xs:boolean"/> |
||||
<xs:element name="recover" type="xs:boolean"/> |
||||
</xs:sequence> |
||||
<xs:element name="job-data-map" type="job-data-mapType" minOccurs="0"/> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="job-data-mapType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a JobDataMap</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:sequence minOccurs="0" maxOccurs="unbounded"> |
||||
<xs:element name="entry" type="entryType"/> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="entryType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a JobDataMap entry</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:sequence> |
||||
<xs:element name="key" type="xs:string"/> |
||||
<xs:element name="value" type="xs:string"/> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="triggerType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a Trigger</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:choice> |
||||
<xs:element name="simple" type="simpleTriggerType"/> |
||||
<xs:element name="cron" type="cronTriggerType"/> |
||||
<xs:element name="calendar-interval" type="calendarIntervalTriggerType"/> |
||||
</xs:choice> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="abstractTriggerType" abstract="true"> |
||||
<xs:annotation> |
||||
<xs:documentation>Common Trigger definitions</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:sequence> |
||||
<xs:element name="name" type="xs:string"/> |
||||
<xs:element name="group" type="xs:string" minOccurs="0"/> |
||||
<xs:element name="description" type="xs:string" minOccurs="0"/> |
||||
<xs:element name="job-name" type="xs:string"/> |
||||
<xs:element name="job-group" type="xs:string" minOccurs="0"/> |
||||
<xs:element name="priority" type="xs:nonNegativeInteger" minOccurs="0"/> |
||||
<xs:element name="calendar-name" type="xs:string" minOccurs="0"/> |
||||
<xs:element name="job-data-map" type="job-data-mapType" minOccurs="0"/> |
||||
<xs:sequence minOccurs="0"> |
||||
<xs:choice> |
||||
<xs:element name="start-time" type="xs:dateTime"/> |
||||
<xs:element name="start-time-seconds-in-future" type="xs:nonNegativeInteger"/> |
||||
</xs:choice> |
||||
<xs:element name="end-time" type="xs:dateTime" minOccurs="0"/> |
||||
</xs:sequence> |
||||
</xs:sequence> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="simpleTriggerType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a SimpleTrigger</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:complexContent> |
||||
<xs:extension base="abstractTriggerType"> |
||||
<xs:sequence> |
||||
<xs:element name="misfire-instruction" type="simple-trigger-misfire-instructionType" minOccurs="0" /> |
||||
<xs:sequence minOccurs="0"> |
||||
<xs:element name="repeat-count" type="repeat-countType"/> |
||||
<xs:element name="repeat-interval" type="xs:nonNegativeInteger"/> |
||||
</xs:sequence> |
||||
</xs:sequence> |
||||
</xs:extension> |
||||
</xs:complexContent> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="cronTriggerType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a CronTrigger</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:complexContent> |
||||
<xs:extension base="abstractTriggerType"> |
||||
<xs:sequence> |
||||
<xs:element name="misfire-instruction" type="cron-trigger-misfire-instructionType" minOccurs="0"/> |
||||
<xs:element name="cron-expression" type="cron-expressionType"/> |
||||
<xs:element name="time-zone" type="xs:string" minOccurs="0"/> |
||||
</xs:sequence> |
||||
</xs:extension> |
||||
</xs:complexContent> |
||||
</xs:complexType> |
||||
|
||||
<xs:complexType name="calendarIntervalTriggerType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Define a DateIntervalTrigger</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:complexContent> |
||||
<xs:extension base="abstractTriggerType"> |
||||
<xs:sequence> |
||||
<xs:element name="misfire-instruction" type="date-interval-trigger-misfire-instructionType" minOccurs="0"/> |
||||
<xs:element name="repeat-interval" type="xs:nonNegativeInteger"/> |
||||
<xs:element name="repeat-interval-unit" type="interval-unitType"/> |
||||
</xs:sequence> |
||||
</xs:extension> |
||||
</xs:complexContent> |
||||
</xs:complexType> |
||||
|
||||
<xs:simpleType name="cron-expressionType"> |
||||
<xs:annotation> |
||||
<xs:documentation> |
||||
Cron expression (see JavaDoc for examples) |
||||
|
||||
Special thanks to Chris Thatcher (thatcher@butterfly.net) for the regular expression! |
||||
|
||||
Regular expressions are not my strong point but I believe this is complete, |
||||
with the caveat that order for expressions like 3-0 is not legal but will pass, |
||||
and month and day names must be capitalized. |
||||
If you want to examine the correctness look for the [\s] to denote the |
||||
seperation of individual regular expressions. This is how I break them up visually |
||||
to examine them: |
||||
|
||||
SECONDS: |
||||
( |
||||
((([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?,)*([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?) |
||||
| (([\*]|[0-9]|[0-5][0-9])/([0-9]|[0-5][0-9])) |
||||
| ([\?]) |
||||
| ([\*]) |
||||
) [\s] |
||||
MINUTES: |
||||
( |
||||
((([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?,)*([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?) |
||||
| (([\*]|[0-9]|[0-5][0-9])/([0-9]|[0-5][0-9])) |
||||
| ([\?]) |
||||
| ([\*]) |
||||
) [\s] |
||||
HOURS: |
||||
( |
||||
((([0-9]|[0-1][0-9]|[2][0-3])(-([0-9]|[0-1][0-9]|[2][0-3]))?,)*([0-9]|[0-1][0-9]|[2][0-3])(-([0-9]|[0-1][0-9]|[2][0-3]))?) |
||||
| (([\*]|[0-9]|[0-1][0-9]|[2][0-3])/([0-9]|[0-1][0-9]|[2][0-3])) |
||||
| ([\?]) |
||||
| ([\*]) |
||||
) [\s] |
||||
DAY OF MONTH: |
||||
( |
||||
((([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(-([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]))?,)*([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(-([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]))?(C)?) |
||||
| (([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])/([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(C)?) |
||||
| (L(-[0-9])?) |
||||
| (L(-[1-2][0-9])?) |
||||
| (L(-[3][0-1])?) |
||||
| (LW) |
||||
| ([1-9]W) |
||||
| ([1-3][0-9]W) |
||||
| ([\?]) |
||||
| ([\*]) |
||||
)[\s] |
||||
MONTH: |
||||
( |
||||
((([1-9]|0[1-9]|1[0-2])(-([1-9]|0[1-9]|1[0-2]))?,)*([1-9]|0[1-9]|1[0-2])(-([1-9]|0[1-9]|1[0-2]))?) |
||||
| (([1-9]|0[1-9]|1[0-2])/([1-9]|0[1-9]|1[0-2])) |
||||
| (((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?,)*(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?) |
||||
| ((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)/(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)) |
||||
| ([\?]) |
||||
| ([\*]) |
||||
)[\s] |
||||
DAY OF WEEK: |
||||
( |
||||
(([1-7](-([1-7]))?,)*([1-7])(-([1-7]))?) |
||||
| ([1-7]/([1-7])) |
||||
| (((MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?,)*(MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?(C)?) |
||||
| ((MON|TUE|WED|THU|FRI|SAT|SUN)/(MON|TUE|WED|THU|FRI|SAT|SUN)(C)?) |
||||
| (([1-7]|(MON|TUE|WED|THU|FRI|SAT|SUN))(L|LW)?) |
||||
| (([1-7]|MON|TUE|WED|THU|FRI|SAT|SUN)#([1-7])?) |
||||
| ([\?]) |
||||
| ([\*]) |
||||
) |
||||
YEAR (OPTIONAL): |
||||
( |
||||
[\s]? |
||||
([\*])? |
||||
| ((19[7-9][0-9])|(20[0-9][0-9]))? |
||||
| (((19[7-9][0-9])|(20[0-9][0-9]))/((19[7-9][0-9])|(20[0-9][0-9])))? |
||||
| ((((19[7-9][0-9])|(20[0-9][0-9]))(-((19[7-9][0-9])|(20[0-9][0-9])))?,)*((19[7-9][0-9])|(20[0-9][0-9]))(-((19[7-9][0-9])|(20[0-9][0-9])))?)? |
||||
) |
||||
</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:restriction base="xs:string"> |
||||
<xs:pattern value="(((([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?,)*([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?)|(([\*]|[0-9]|[0-5][0-9])/([0-9]|[0-5][0-9]))|([\?])|([\*]))[\s](((([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?,)*([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?)|(([\*]|[0-9]|[0-5][0-9])/([0-9]|[0-5][0-9]))|([\?])|([\*]))[\s](((([0-9]|[0-1][0-9]|[2][0-3])(-([0-9]|[0-1][0-9]|[2][0-3]))?,)*([0-9]|[0-1][0-9]|[2][0-3])(-([0-9]|[0-1][0-9]|[2][0-3]))?)|(([\*]|[0-9]|[0-1][0-9]|[2][0-3])/([0-9]|[0-1][0-9]|[2][0-3]))|([\?])|([\*]))[\s](((([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(-([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]))?,)*([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(-([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]))?(C)?)|(([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])/([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(C)?)|(L(-[0-9])?)|(L(-[1-2][0-9])?)|(L(-[3][0-1])?)|(LW)|([1-9]W)|([1-3][0-9]W)|([\?])|([\*]))[\s](((([1-9]|0[1-9]|1[0-2])(-([1-9]|0[1-9]|1[0-2]))?,)*([1-9]|0[1-9]|1[0-2])(-([1-9]|0[1-9]|1[0-2]))?)|(([1-9]|0[1-9]|1[0-2])/([1-9]|0[1-9]|1[0-2]))|(((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?,)*(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?)|((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)/(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))|([\?])|([\*]))[\s]((([1-7](-([1-7]))?,)*([1-7])(-([1-7]))?)|([1-7]/([1-7]))|(((MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?,)*(MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?(C)?)|((MON|TUE|WED|THU|FRI|SAT|SUN)/(MON|TUE|WED|THU|FRI|SAT|SUN)(C)?)|(([1-7]|(MON|TUE|WED|THU|FRI|SAT|SUN))?(L|LW)?)|(([1-7]|MON|TUE|WED|THU|FRI|SAT|SUN)#([1-7])?)|([\?])|([\*]))([\s]?(([\*])?|(19[7-9][0-9])|(20[0-9][0-9]))?| (((19[7-9][0-9])|(20[0-9][0-9]))/((19[7-9][0-9])|(20[0-9][0-9])))?| ((((19[7-9][0-9])|(20[0-9][0-9]))(-((19[7-9][0-9])|(20[0-9][0-9])))?,)*((19[7-9][0-9])|(20[0-9][0-9]))(-((19[7-9][0-9])|(20[0-9][0-9])))?)?)"/> |
||||
</xs:restriction> |
||||
</xs:simpleType> |
||||
|
||||
<xs:simpleType name="repeat-countType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Number of times to repeat the Trigger (-1 for indefinite)</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:restriction base="xs:integer"> |
||||
<xs:minInclusive value="-1"/> |
||||
</xs:restriction> |
||||
</xs:simpleType> |
||||
|
||||
|
||||
<xs:simpleType name="simple-trigger-misfire-instructionType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Simple Trigger Misfire Instructions</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:restriction base="xs:string"> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_SMART_POLICY"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_FIRE_NOW"/> |
||||
</xs:restriction> |
||||
</xs:simpleType> |
||||
|
||||
<xs:simpleType name="cron-trigger-misfire-instructionType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Cron Trigger Misfire Instructions</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:restriction base="xs:string"> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_SMART_POLICY"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_DO_NOTHING"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_FIRE_ONCE_NOW"/> |
||||
</xs:restriction> |
||||
</xs:simpleType> |
||||
|
||||
<xs:simpleType name="date-interval-trigger-misfire-instructionType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Date Interval Trigger Misfire Instructions</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:restriction base="xs:string"> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_SMART_POLICY"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_DO_NOTHING"/> |
||||
<xs:pattern value="MISFIRE_INSTRUCTION_FIRE_ONCE_NOW"/> |
||||
</xs:restriction> |
||||
</xs:simpleType> |
||||
|
||||
<xs:simpleType name="interval-unitType"> |
||||
<xs:annotation> |
||||
<xs:documentation>Interval Units</xs:documentation> |
||||
</xs:annotation> |
||||
<xs:restriction base="xs:string"> |
||||
<xs:pattern value="DAY"/> |
||||
<xs:pattern value="HOUR"/> |
||||
<xs:pattern value="MINUTE"/> |
||||
<xs:pattern value="MONTH"/> |
||||
<xs:pattern value="SECOND"/> |
||||
<xs:pattern value="WEEK"/> |
||||
<xs:pattern value="YEAR"/> |
||||
</xs:restriction> |
||||
</xs:simpleType> |
||||
|
||||
</xs:schema> |
Loading…
Reference in new issue