1 4 package org.oddjob.quartz; 5 6 import java.io.IOException ; 7 import java.io.ObjectInputStream ; 8 import java.io.ObjectOutputStream ; 9 import java.io.Serializable ; 10 import java.util.ArrayList ; 11 import java.util.Date ; 12 import java.util.HashMap ; 13 import java.util.Iterator ; 14 import java.util.List ; 15 import java.util.Map ; 16 import java.util.Properties ; 17 18 import org.apache.log4j.Logger; 19 import org.oddjob.OddjobException; 20 import org.oddjob.Stateful; 21 import org.oddjob.Structural; 22 import org.oddjob.arooa.ArooaConstants; 23 import org.oddjob.arooa.ArooaContext; 24 import org.oddjob.arooa.Lifecycle; 25 import org.oddjob.arooa.registry.ComponentRegistry; 26 import org.oddjob.arooa.registry.Path; 27 import org.oddjob.monitor.model.Describer; 28 import org.oddjob.persist.ComponentPersister; 29 import org.oddjob.scheduling.OddjobScheduler; 30 import org.oddjob.scheduling.ScheduleInstruction; 31 import org.oddjob.scheduling.ScheduleSummary; 32 import org.oddjob.state.JobState; 33 import org.oddjob.state.JobStateEvent; 34 import org.oddjob.state.JobStateHandler; 35 import org.oddjob.state.JobStateListener; 36 import org.oddjob.structural.ChildHelper; 37 import org.oddjob.structural.StructuralEvent; 38 import org.oddjob.structural.StructuralListener; 39 import org.oddjob.util.OddjobConfigException; 40 import org.quartz.Scheduler; 41 import org.quartz.SchedulerException; 42 import org.quartz.SchedulerMetaData; 43 import org.quartz.Trigger; 44 import org.quartz.impl.StdSchedulerFactory; 45 46 122 public class QuartzSchedulerJob 123 implements Structural, OddjobScheduler { 124 private static final Logger logger = Logger.getLogger(QuartzSchedulerJob.class); 125 126 131 private String name; 132 133 139 private Properties properties = new Properties (); 140 141 147 private ComponentPersister persister; 148 149 150 private Scheduler scheduler; 151 152 153 private ChildHelper childHelper = new ChildHelper(this); 154 155 160 private transient ScheduleInstruction[] schedules; 161 162 163 private transient Map scheduled = new HashMap (); 164 165 166 private transient Map idsToJob = new HashMap (); 167 168 170 private transient ComponentRegistry parentRegistry; 171 172 173 private transient ComponentRegistry scheduleRegistry; 174 175 178 private String id; 179 180 185 public void setId(String id) { 186 this.id = id; 187 } 188 189 190 195 public String getName() { 196 return name; 197 } 198 199 204 public void setName(String name) { 205 this.name = name; 206 } 207 208 214 public void setProperty(String name, String value) { 215 properties.setProperty(name, value); 216 } 217 218 223 public String getProperty(String name) { 224 return properties.getProperty(name); 225 } 226 227 232 public void setSchedules(ScheduleInstruction[] schedules) { 233 this.schedules = schedules; 234 } 235 236 241 public ScheduleInstruction[] getSchedules() { 242 return schedules; 243 } 244 245 248 public ComponentPersister getPersister() { 249 return persister; 250 } 251 252 255 public void setPersister(ComponentPersister persister) { 256 this.persister = persister; 257 } 258 259 263 public boolean canSchedule(Object component) { 264 if (component == null) { 266 return false; 267 } 268 return (scheduler != null); 269 } 270 271 275 public void schedule(ScheduleInstruction si) { 276 String id = si.getId(); 277 if (id == null) { 278 throw new OddjobConfigException("Schedule has no id."); 279 } 280 synchronized (childHelper) { 281 if (scheduler == null) { 282 throw new OddjobException("Scheduler not running!"); 283 } 284 if (scheduled.get(id) != null) { 285 logger.debug("A schedule already exists with id [" + id + "], unsheduling frist."); 286 unSchedule(id); 287 } 288 QuartzSchedule quartzSchedule = (QuartzSchedule) 289 new QuartzScheduleFactory().createSchedule(si, 290 parentRegistry); 291 292 logger.debug("Scheduling id [" + si.getId() + "]."); 293 try { 294 quartzSchedule.scheduleWith(scheduler); 295 scheduled.put(id, quartzSchedule); 296 idsToJob.put(id, si.getJob()); 297 scheduleRegistry.register(id, quartzSchedule); 298 childHelper.addChild(quartzSchedule); 299 } catch (Throwable t) { 300 logger.error("Failed to schedule.", t); 301 } 302 } 303 304 } 305 306 private void restore(String id) { 307 try { 308 QuartzSchedule quartzSchedule 309 = (QuartzSchedule) persister.restore(id); 310 quartzSchedule.setComponentRegistry(parentRegistry); 311 quartzSchedule.scheduleWith(scheduler); 312 scheduled.put(id, quartzSchedule); 313 scheduleRegistry.register(id, quartzSchedule); 315 childHelper.addChild(quartzSchedule); 316 } catch (Throwable t) { 317 logger.error("Failed to schedule.", t); 318 } 319 } 320 321 protected String [] sheduledIds() { 322 return (String []) idsToJob.keySet().toArray(new String [0]); 323 } 324 325 329 public void unSchedule(String id) { 330 synchronized(childHelper) { 331 QuartzSchedule quartzSchedule = (QuartzSchedule) scheduled.get(id); 332 if (quartzSchedule == null) { 333 return; 334 } 335 try { 336 quartzSchedule.unscheduleFrom(scheduler); 337 childHelper.removeChild(quartzSchedule); 338 scheduled.remove(id); 339 idsToJob.remove(id); 340 scheduleRegistry.remove(id); 341 Lifecycle.destroy(quartzSchedule); 342 } catch (Throwable t) { 343 logger.error("Failed to schedule.", t); 344 } 345 } 346 347 } 348 349 353 public ScheduleSummary[] summariesFor(Object object) { 354 if (object == null) { 355 return new ScheduleSummary[0]; 356 } 357 List results = new ArrayList (); 358 synchronized (childHelper) { 359 for (Iterator it = scheduled.entrySet().iterator(); it.hasNext(); ) { 360 Map.Entry entry = (Map.Entry ) it.next(); 361 String id = (String ) entry.getKey(); 362 if (idsToJob.get(id) != object) { 363 continue; 364 } 365 Object schedule = entry.getValue(); 366 Map description = Describer.describe(schedule); 367 ScheduleSummary summary = new ScheduleSummary(); 368 summary.setId(id); 369 summary.setDescription(description); 370 results.add(summary); 371 } 372 } 373 return (ScheduleSummary[]) results.toArray(new ScheduleSummary[0]); 374 } 375 376 380 public boolean setContext(ArooaContext context) { 381 parentRegistry = (ComponentRegistry) context.get( 382 ArooaConstants.COMPONENT_REGISTRY); 383 return true; 384 } 385 386 391 public void start() throws SchedulerException { 392 StdSchedulerFactory factory = null; 393 if (properties.size() > 0) { 394 factory = new StdSchedulerFactory(properties); 395 } else { 396 factory = new StdSchedulerFactory(); 397 } 398 399 if (persister != null && id == null) { 401 throw new IllegalStateException ("Scheduler must have an Id for persistence."); 402 } 403 404 scheduleRegistry = new ComponentRegistry(); 405 Object maybeProxy = this; 406 if (parentRegistry == null) { 408 parentRegistry = new ComponentRegistry(); 409 } 410 else if (id != null) { 411 maybeProxy = parentRegistry.objectForPath(new Path(id)); 412 } 413 parentRegistry.addChild(scheduleRegistry, maybeProxy); 414 415 synchronized (childHelper) { 416 scheduler = factory.getScheduler(); 417 scheduler.start(); 418 419 SchedulerState schedulerState = null; 420 if (persister != null) { 421 schedulerState = (SchedulerState) persister.restore(id); 422 SchedulerState newState = new SchedulerState(); 424 this.addStructuralListener(newState); 425 scheduleRegistry.register(id, newState); 426 persister.setRoot(newState); 427 persister.initialise(scheduleRegistry); 428 } 429 430 if (schedulerState != null) { 432 for (int i = 0; schedulerState.savedIds != null 433 && i < schedulerState.savedIds.length; ++i) { 434 restore(schedulerState.savedIds[i]); 435 } 436 } 437 else if (schedules != null) { 438 for (int i = 0; i < schedules.length; ++i) { 439 schedule(schedules[i]); 440 } 441 } 442 } 443 } 444 445 public void stop() throws SchedulerException { 446 scheduler.shutdown(true); 449 scheduler = null; 450 if (persister != null) { 451 persister.close(); 452 removeStructuralListener((StructuralListener) persister.getRoot()); 453 } 454 parentRegistry.removeChild(this); 455 childHelper.destroyAll(); 456 } 457 458 465 public Object lookup(String path) throws IllegalStateException { 466 if (parentRegistry == null) { 467 throw new IllegalStateException ("Scheduler must be run before a lookup is possible"); 468 } 469 ComponentRegistry componentRegistry = parentRegistry.registryOwnedBy(this); 470 if (componentRegistry == null) { 471 throw new IllegalStateException ("Scheduler not running."); 472 } 473 Object found = componentRegistry.objectForPath(new Path(path)); 474 logger.debug("lookup [" + path + "] found [" + found + "]"); 475 return found; 476 } 477 478 484 public void addStructuralListener(StructuralListener listener) { 485 childHelper.addStructuralListener(listener); 486 } 487 488 493 public void removeStructuralListener(StructuralListener listener) { 494 childHelper.removeStructuralListener(listener); 495 } 496 497 504 public Date getTimeNow() { 505 return new Date (); 506 } 507 508 public String toString() { 509 if (name == null) { 510 return "A Scheduler"; 511 } 512 return name; 513 } 514 515 522 public void setLogDump(String value) throws SchedulerException { 523 if (scheduler == null) { 524 logger.info("Scheduler not running."); 525 } 526 SchedulerMetaData smd = scheduler.getMetaData(); 527 logger.info("Scheduler Summary:" + smd.getSummary()); 528 529 String groups[] = scheduler.getJobGroupNames(); 530 for (int g = 0; g < groups.length; ++g) { 531 String jobs[] = scheduler.getJobNames(groups[g]); 532 for (int j = 0; j < jobs.length; ++j) { 533 Trigger[] triggers = scheduler.getTriggersOfJob(jobs[j], groups[g]); 534 for (int t = 0; t < triggers.length; ++t) { 535 Trigger trigger = triggers[t]; 536 logger.info(trigger.getFullJobName() 537 + "(" + trigger.getName() + ") : " 538 + "Start time [" + trigger.getStartTime() + "] " 539 + "Previous time [" + trigger.getPreviousFireTime() + "] " 540 + "Next time [" + trigger.getNextFireTime() + "] " 541 ); 542 } 543 } 544 } 545 } 546 547 public static class SchedulerState 548 implements Serializable , Stateful, Structural, StructuralListener { 549 private static final long serialVersionUID = 20060112; 550 551 private transient JobStateHandler stateHandler= new JobStateHandler(this); 552 553 private String [] savedIds; 554 555 private transient ChildHelper childHelper = new ChildHelper(this); 556 557 public void childAdded(StructuralEvent event) { 558 QuartzSchedulerJob scheduler = 559 (QuartzSchedulerJob) event.getSource(); 560 savedIds = scheduler.sheduledIds(); 561 childHelper.insertChild(event.getIndex(), event.getChild()); 562 stateHandler.fireEvent( 563 new JobStateEvent(this, JobState.COMPLETE)); 564 } 565 566 public void childRemoved(StructuralEvent event) { 567 QuartzSchedulerJob scheduler = 568 (QuartzSchedulerJob) event.getSource(); 569 savedIds = scheduler.sheduledIds(); 570 stateHandler.fireEvent( 571 new JobStateEvent(this, JobState.COMPLETE)); 572 childHelper.removeChildAt(event.getIndex()); 573 } 574 575 public void addStructuralListener(StructuralListener listener) { 576 childHelper.addStructuralListener(listener); 577 } 578 579 public void removeStructuralListener(StructuralListener listener) { 580 childHelper.removeStructuralListener(listener); 581 } 582 583 private void writeObject(ObjectOutputStream s) 584 throws IOException { 585 s.defaultWriteObject(); 586 } 587 588 private void readObject(ObjectInputStream s) 589 throws IOException , ClassNotFoundException { 590 s.defaultReadObject(); 591 stateHandler = new JobStateHandler(this); 592 childHelper = new ChildHelper(this); 593 } 594 595 public void addJobStateListener(JobStateListener listener) { 596 stateHandler.addJobStateListener(listener); 597 } 598 599 public void removeJobStateListener(JobStateListener listener) { 600 stateHandler.removeJobStateListener(listener); 601 } 602 603 } 604 } 605 | Popular Tags |