解决这个问题的原文:
http://www.gmjjavadesigns.com/gmjd/en_US/entry/quartz_1_6_and_oc4j
代码:
/*
* 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 edu.unc.its.as.affiliate.quartz;
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.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import javax.transaction.UserTransaction;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.jobs.FileScanJob;
import org.quartz.jobs.FileScanListener;
import org.quartz.plugins.SchedulerPluginWithUserTransactionSupport;
import org.quartz.simpl.CascadingClassLoadHelper;
import org.quartz.spi.ClassLoadHelper;
import org.quartz.xml.JobSchedulingDataProcessor;
/**
* 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.
*
*
* The periodically scanning of files for changes is not currently supported in a * clustered environment. *
* ** If using the JobInitializationPlugin with JobStoreCMT, be sure to set the * plugin property wrapInUserTransaction to true. Also, if have a * positive scanInterval be sure to set * org.quartz.scheduler.wrapJobExecutionInUserTransaction to true. *
* * @author James House * @author Pierre Awaragi */ public class JobInitializationPlugin extends SchedulerPluginWithUserTransactionSupport implements FileScanListener { /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Data members. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ private static final int MAX_JOB_TRIGGER_NAME_LEN = 80; private static final String JOB_INITIALIZATION_PLUGIN_NAME = "JobInitializationPlugin"; private static final String FILE_NAME_DELIMITERS = ","; private boolean overWriteExistingJobs = false; private boolean failOnFileNotFound = true; private String fileNames = JobSchedulingDataProcessor.QUARTZ_XML_FILE_NAME; // Populated by initialization private Map jobFiles = new HashMap(); private boolean useContextClassLoader = true; private boolean validating = false; private boolean validatingSchema = true; private long scanInterval = 0; boolean started = false; protected ClassLoadHelper classLoadHelper = null; private Set jobTriggerNameSet = new HashSet(); /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constructors. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public JobInitializationPlugin() { } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Interface. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** * The file name (and path) to the XML file that should be read. * @deprecated Use fileNames with just one file. */ public String getFileName() { return fileNames; } /** * The file name (and path) to the XML file that should be read. * @deprecated Use fileNames with just one file. */ public void setFileName(String fileName) { getLog().warn("The /"filename/" plugin property is deprecated. Please use /"filenames/" in the future."); this.fileNames = fileName; } /** * 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; } /** * Whether or not jobs defined in the XML file should be overwrite existing * jobs with the same name. */ public boolean isOverWriteExistingJobs() { return overWriteExistingJobs; } /** * Whether or not jobs defined in the XML file should be overwrite existing * jobs with the same name. * * @param overWriteExistingJobs */ public void setOverWriteExistingJobs(boolean overWriteExistingJobs) { this.overWriteExistingJobs = overWriteExistingJobs; } /** * 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 istrue
.
*/
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 true
.
*/
public void setFailOnFileNotFound(boolean failOnFileNotFound) {
this.failOnFileNotFound = failOnFileNotFound;
}
/**
* Whether or not the context class loader should be used. Default is true
.
*/
public boolean isUseContextClassLoader() {
return useContextClassLoader;
}
/**
* Whether or not context class loader should be used. Default is true
.
*/
public void setUseContextClassLoader(boolean useContextClassLoader) {
this.useContextClassLoader = useContextClassLoader;
}
/**
* Whether or not the XML should be validated. Default is false
.
*/
public boolean isValidating() {
return validating;
}
/**
* Whether or not the XML should be validated. Default is false
.
*/
public void setValidating(boolean validating) {
this.validating = validating;
}
/**
* Whether or not the XML schema should be validated. Default is true
.
*/
public boolean isValidatingSchema() {
return validatingSchema;
}
/**
* Whether or not the XML schema should be validated. Default is true
.
*/
public void setValidatingSchema(boolean validatingSchema) {
this.validatingSchema = validatingSchema;
}
/*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* SchedulerPlugin Interface.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/**
*
* Called during creation of the Scheduler
in order to give
* the SchedulerPlugin
a chance to initialize.
*
Scheduler
.
*/
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() == false)) {
return;
}
JobSchedulingDataProcessor processor =
new JobSchedulingDataProcessor(isUseContextClassLoader(), isValidating(), isValidatingSchema());
try {
processor.processFileAndScheduleJobs(
jobFile.getFilePath(),
jobFile.getFilePath(), // systemId
getScheduler(),
isOverWriteExistingJobs());
} catch (Exception e) {
getLog().error("Error scheduling jobs: " + e.getMessage(), e);
}
}
public void processFile(String filePath) {
processFile((JobFile)jobFiles.get(filePath));
}
/**
* @see org.quartz.jobs.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) {
// we need jdk 1.3 compatibility, so we abandon this code...
try {
furl = URLDecoder.decode(url.toString(), "UTF-8");
} catch (UnsupportedEncodingException e) {
furl = url.toString();
}
// furl = URLDecoder.decode(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;
// commented out and addede new line to get url path for a file
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