1 17 18 21 package org.quartz.plugins.xml; 22 23 import java.io.File ; 24 import java.io.FileNotFoundException ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.net.URL ; 28 import java.net.URLDecoder ; 29 import java.util.Date ; 30 import java.util.HashMap ; 31 import java.util.HashSet ; 32 import java.util.Iterator ; 33 import java.util.Map ; 34 import java.util.Set ; 35 import java.util.StringTokenizer ; 36 37 import javax.transaction.UserTransaction ; 38 39 import org.quartz.JobDetail; 40 import org.quartz.Scheduler; 41 import org.quartz.SchedulerException; 42 import org.quartz.SimpleTrigger; 43 import org.quartz.jobs.FileScanJob; 44 import org.quartz.jobs.FileScanListener; 45 import org.quartz.plugins.SchedulerPluginWithUserTransactionSupport; 46 import org.quartz.simpl.CascadingClassLoadHelper; 47 import org.quartz.spi.ClassLoadHelper; 48 import org.quartz.xml.JobSchedulingDataProcessor; 49 50 70 public class JobInitializationPlugin 71 extends SchedulerPluginWithUserTransactionSupport 72 implements FileScanListener { 73 74 81 private static final int MAX_JOB_TRIGGER_NAME_LEN = 80; 82 private static final String JOB_INITIALIZATION_PLUGIN_NAME = "JobInitializationPlugin"; 83 private static final String FILE_NAME_DELIMITERS = ","; 84 85 private boolean overWriteExistingJobs = false; 86 87 private boolean failOnFileNotFound = true; 88 89 private String fileNames = JobSchedulingDataProcessor.QUARTZ_XML_FILE_NAME; 90 91 private Map jobFiles = new HashMap (); 93 94 private boolean useContextClassLoader = true; 95 96 private boolean validating = false; 97 98 private boolean validatingSchema = true; 99 100 private long scanInterval = 0; 101 102 boolean started = false; 103 104 protected ClassLoadHelper classLoadHelper = null; 105 106 private Set jobTriggerNameSet = new HashSet (); 107 108 115 116 public JobInitializationPlugin() { 117 } 118 119 126 127 131 public String getFileName() { 132 return fileNames; 133 } 134 135 139 public void setFileName(String fileName) { 140 getLog().warn("The \"filename\" plugin property is deprecated. Please use \"filenames\" in the future."); 141 this.fileNames = fileName; 142 } 143 144 147 public String getFileNames() { 148 return fileNames; 149 } 150 151 154 public void setFileNames(String fileNames) { 155 this.fileNames = fileNames; 156 } 157 158 162 public boolean isOverWriteExistingJobs() { 163 return overWriteExistingJobs; 164 } 165 166 172 public void setOverWriteExistingJobs(boolean overWriteExistingJobs) { 173 this.overWriteExistingJobs = overWriteExistingJobs; 174 } 175 176 183 public long getScanInterval() { 184 return scanInterval / 1000; 185 } 186 187 194 public void setScanInterval(long scanInterval) { 195 this.scanInterval = scanInterval * 1000; 196 } 197 198 202 public boolean isFailOnFileNotFound() { 203 return failOnFileNotFound; 204 } 205 206 210 public void setFailOnFileNotFound(boolean failOnFileNotFound) { 211 this.failOnFileNotFound = failOnFileNotFound; 212 } 213 214 217 public boolean isUseContextClassLoader() { 218 return useContextClassLoader; 219 } 220 221 224 public void setUseContextClassLoader(boolean useContextClassLoader) { 225 this.useContextClassLoader = useContextClassLoader; 226 } 227 228 231 public boolean isValidating() { 232 return validating; 233 } 234 235 238 public void setValidating(boolean validating) { 239 this.validating = validating; 240 } 241 242 245 public boolean isValidatingSchema() { 246 return validatingSchema; 247 } 248 249 252 public void setValidatingSchema(boolean validatingSchema) { 253 this.validatingSchema = validatingSchema; 254 } 255 256 263 264 273 public void initialize(String name, final Scheduler scheduler) 274 throws SchedulerException { 275 super.initialize(name, scheduler); 276 277 classLoadHelper = new CascadingClassLoadHelper(); 278 classLoadHelper.initialize(); 279 280 getLog().info("Registering Quartz Job Initialization Plug-in."); 281 282 StringTokenizer stok = new StringTokenizer (fileNames, FILE_NAME_DELIMITERS); 284 while (stok.hasMoreTokens()) { 285 JobFile jobFile = new JobFile(stok.nextToken()); 286 jobFiles.put(jobFile.getFilePath(), jobFile); 287 } 288 } 289 290 291 public void start(UserTransaction userTransaction) { 292 try { 293 if (jobFiles.isEmpty() == false) { 294 295 if (scanInterval > 0) { 296 getScheduler().getContext().put(JOB_INITIALIZATION_PLUGIN_NAME + '_' + getName(), this); 297 } 298 299 Iterator iterator = jobFiles.values().iterator(); 300 while (iterator.hasNext()) { 301 JobFile jobFile = (JobFile)iterator.next(); 302 303 if (scanInterval > 0) { 304 String jobTriggerName = buildJobTriggerName(jobFile.getFileBasename()); 305 306 SimpleTrigger trig = new SimpleTrigger( 307 jobTriggerName, 308 JOB_INITIALIZATION_PLUGIN_NAME, 309 new Date (), null, 310 SimpleTrigger.REPEAT_INDEFINITELY, scanInterval); 311 trig.setVolatility(true); 312 313 JobDetail job = new JobDetail( 314 jobTriggerName, 315 JOB_INITIALIZATION_PLUGIN_NAME, 316 FileScanJob.class); 317 job.setVolatility(true); 318 job.getJobDataMap().put(FileScanJob.FILE_NAME, jobFile.getFilePath()); 319 job.getJobDataMap().put(FileScanJob.FILE_SCAN_LISTENER_NAME, JOB_INITIALIZATION_PLUGIN_NAME + '_' + getName()); 320 321 getScheduler().scheduleJob(job, trig); 322 } 323 324 processFile(jobFile); 325 } 326 } 327 } catch(SchedulerException se) { 328 getLog().error("Error starting background-task for watching jobs file.", se); 329 } finally { 330 started = true; 331 } 332 } 333 334 339 private String buildJobTriggerName( 340 String fileBasename) { 341 String jobTriggerName = JOB_INITIALIZATION_PLUGIN_NAME + '_' + getName() + '_' + fileBasename.replace('.', '_'); 344 345 if (jobTriggerName.length() > MAX_JOB_TRIGGER_NAME_LEN) { 347 jobTriggerName = jobTriggerName.substring(0, MAX_JOB_TRIGGER_NAME_LEN); 348 } 349 350 int currentIndex = 1; 355 while (jobTriggerNameSet.add(jobTriggerName) == false) { 356 if (currentIndex > 1) { 358 jobTriggerName = jobTriggerName.substring(0, jobTriggerName.lastIndexOf('_')); 359 } 360 361 String numericSuffix = "_" + currentIndex++; 362 363 if (jobTriggerName.length() > (MAX_JOB_TRIGGER_NAME_LEN - numericSuffix.length())) { 365 jobTriggerName = jobTriggerName.substring(0, (MAX_JOB_TRIGGER_NAME_LEN - numericSuffix.length())); 366 } 367 368 jobTriggerName += numericSuffix; 369 } 370 371 return jobTriggerName; 372 } 373 374 378 public void shutdown() { 379 } 382 383 private void processFile(JobFile jobFile) { 384 if ((jobFile == null) || (jobFile.getFileFound() == false)) { 385 return; 386 } 387 388 JobSchedulingDataProcessor processor = 389 new JobSchedulingDataProcessor(isUseContextClassLoader(), isValidating(), isValidatingSchema()); 390 391 try { 392 processor.processFileAndScheduleJobs( 393 jobFile.getFilePath(), 394 jobFile.getFilePath(), getScheduler(), 396 isOverWriteExistingJobs()); 397 } catch (Exception e) { 398 getLog().error("Error scheduling jobs: " + e.getMessage(), e); 399 } 400 } 401 402 public void processFile(String filePath) { 403 processFile((JobFile)jobFiles.get(filePath)); 404 } 405 406 409 public void fileUpdated(String fileName) { 410 if (started) { 411 processFile(fileName); 412 } 413 } 414 415 class JobFile { 416 private String fileName; 417 418 private String filePath; 420 private String fileBasename; 421 private boolean fileFound; 422 423 protected JobFile(String fileName) throws SchedulerException { 424 this.fileName = fileName; 425 initialize(); 426 } 427 428 protected String getFileName() { 429 return fileName; 430 } 431 432 protected boolean getFileFound() { 433 return fileFound; 434 } 435 436 protected String getFilePath() { 437 return filePath; 438 } 439 440 protected String getFileBasename() { 441 return fileBasename; 442 } 443 444 private void initialize() throws SchedulerException { 445 InputStream f = null; 446 try { 447 String furl = null; 448 449 File file = new File (getFileName()); if (!file.exists()) { 451 URL url = classLoadHelper.getResource(getFileName()); 452 if(url != null) { 453 furl = URLDecoder.decode(url.getPath()); 460 file = new File (furl); 461 try { 462 f = url.openStream(); 463 } catch (IOException ignor) { 464 } 466 } 467 } else { 468 try { 469 f = new java.io.FileInputStream (file); 470 }catch (FileNotFoundException e) { 471 } 473 } 474 475 if (f == null) { 476 if (isFailOnFileNotFound()) { 477 throw new SchedulerException( 478 "File named '" + getFileName() + "' does not exist."); 479 } else { 480 getLog().warn("File named '" + getFileName() + "' does not exist."); 481 } 482 } else { 483 fileFound = true; 484 filePath = (furl != null) ? furl : file.getAbsolutePath(); 485 fileBasename = file.getName(); 486 } 487 } finally { 488 try { 489 if (f != null) { 490 f.close(); 491 } 492 } catch (IOException ioe) { 493 getLog().warn("Error closing jobs file " + getFileName(), ioe); 494 } 495 } 496 } 497 } 498 } 499 500 | Popular Tags |