View Javadoc

1   package com.atlassian.scheduler.quartz2;
2   
3   import com.atlassian.scheduler.config.RunMode;
4   import com.atlassian.scheduler.core.AbstractSchedulerService;
5   import org.quartz.Job;
6   import org.quartz.JobDetail;
7   import org.quartz.JobExecutionContext;
8   import org.quartz.JobExecutionException;
9   import org.quartz.Scheduler;
10  import org.quartz.SchedulerException;
11  import org.quartz.simpl.SimpleJobFactory;
12  import org.quartz.spi.JobFactory;
13  import org.quartz.spi.TriggerFiredBundle;
14  
15  import static com.atlassian.util.concurrent.Assertions.notNull;
16  
17  /**
18   * Assigned to the real scheduler so that we can escape the Quartz-centric world.
19   *
20   * @since v1.0
21   */
22  class Quartz2JobFactory extends SimpleJobFactory implements JobFactory {
23      private final AbstractSchedulerService schedulerService;
24      private final RunMode schedulerRunMode;
25  
26      Quartz2JobFactory(AbstractSchedulerService schedulerService, RunMode schedulerRunMode) {
27          this.schedulerService = notNull("schedulerService", schedulerService);
28          this.schedulerRunMode = notNull("schedulerRunMode", schedulerRunMode);
29      }
30  
31      @Override
32      public Job newJob(final TriggerFiredBundle bundle, final Scheduler scheduler) throws SchedulerException {
33          final JobDetail jobDetail = bundle.getJobDetail();
34          if (Quartz2Job.class.equals(jobDetail.getJobClass())) {
35              return new Quartz2Job(schedulerService, schedulerRunMode, bundle);
36          }
37          return new ClassLoaderProtectingWrappedJob(super.newJob(bundle, scheduler), schedulerService);
38      }
39  
40      // SCHEDULER-11: Ensure that the Job runs with its own class loader set as the thread's CCL
41      static class ClassLoaderProtectingWrappedJob implements Job {
42          private final Job delegate;
43          private final AbstractSchedulerService service;
44  
45          ClassLoaderProtectingWrappedJob(Job delegate, AbstractSchedulerService service) {
46              this.service = service;
47              this.delegate = notNull("delegate", delegate);
48          }
49  
50          @Override
51          public void execute(JobExecutionContext context) throws JobExecutionException {
52              service.preJob();
53              final Thread thd = Thread.currentThread();
54              final ClassLoader originalClassLoader = thd.getContextClassLoader();
55              try {
56                  thd.setContextClassLoader(delegate.getClass().getClassLoader());
57                  delegate.execute(context);
58              } finally {
59                  thd.setContextClassLoader(originalClassLoader);
60                  service.postJob();
61              }
62          }
63      }
64  }