1 2 18 19 22 package org.quartz.core; 23 24 import java.io.IOException ; 25 import java.io.InputStream ; 26 import java.rmi.RemoteException ; 27 import java.rmi.registry.LocateRegistry ; 28 import java.rmi.registry.Registry ; 29 import java.rmi.server.UnicastRemoteObject ; 30 import java.util.ArrayList ; 31 import java.util.Date ; 32 import java.util.HashMap ; 33 import java.util.HashSet ; 34 import java.util.LinkedList ; 35 import java.util.List ; 36 import java.util.Properties ; 37 import java.util.Random ; 38 import java.util.Set ; 39 40 import org.apache.commons.logging.Log; 41 import org.apache.commons.logging.LogFactory; 42 import org.quartz.Calendar; 43 import org.quartz.InterruptableJob; 44 import org.quartz.Job; 45 import org.quartz.JobDataMap; 46 import org.quartz.JobDetail; 47 import org.quartz.JobExecutionContext; 48 import org.quartz.JobExecutionException; 49 import org.quartz.JobListener; 50 import org.quartz.JobPersistenceException; 51 import org.quartz.ObjectAlreadyExistsException; 52 import org.quartz.Scheduler; 53 import org.quartz.SchedulerContext; 54 import org.quartz.SchedulerException; 55 import org.quartz.SchedulerListener; 56 import org.quartz.listeners.SchedulerListenerSupport; 57 import org.quartz.Trigger; 58 import org.quartz.TriggerListener; 59 import org.quartz.UnableToInterruptJobException; 60 import org.quartz.impl.SchedulerRepository; 61 import org.quartz.simpl.SimpleJobFactory; 62 import org.quartz.spi.JobFactory; 63 import org.quartz.spi.SchedulerPlugin; 64 import org.quartz.spi.SchedulerSignaler; 65 66 80 public class QuartzScheduler implements RemotableQuartzScheduler { 81 82 89 90 private static String VERSION_MAJOR = "UNKNOWN"; 91 private static String VERSION_MINOR = "UNKNOWN"; 92 private static String VERSION_ITERATION = "UNKNOWN"; 93 94 static { 95 Properties props = new Properties (); 96 try { 97 InputStream is = 98 QuartzScheduler.class.getResourceAsStream("/build.properties"); 99 if(is != null) { 100 props.load(is); 101 VERSION_MAJOR = props.getProperty("version.major"); 102 VERSION_MINOR = props.getProperty("version.minor"); 103 VERSION_ITERATION = props.getProperty("version.iter"); 104 } 105 } catch (IOException e) { 106 (LogFactory.getLog(QuartzScheduler.class)).error( 107 "Error loading version info from build.properties.", e); 108 } 109 } 110 111 112 119 120 private QuartzSchedulerResources resources; 121 122 private QuartzSchedulerThread schedThread; 123 124 private ThreadGroup threadGroup; 125 126 private SchedulerContext context = new SchedulerContext(); 127 128 private HashMap jobListeners = new HashMap (10); 129 130 private HashMap globalJobListeners = new HashMap (10); 131 132 private HashMap triggerListeners = new HashMap (10); 133 134 private HashMap globalTriggerListeners = new HashMap (10); 135 136 private ArrayList schedulerListeners = new ArrayList (10); 137 138 private JobFactory jobFactory = new SimpleJobFactory(); 139 140 ExecutingJobsManager jobMgr = null; 141 142 ErrorLogger errLogger = null; 143 144 private SchedulerSignaler signaler; 145 146 private Random random = new Random (); 147 148 private ArrayList holdToPreventGC = new ArrayList (5); 149 150 private boolean signalOnSchedulingChange = true; 151 152 private boolean closed = false; 153 154 private Date initialStart = null; 155 156 private final Log log = LogFactory.getLog(getClass()); 157 158 165 166 174 public QuartzScheduler(QuartzSchedulerResources resources, 175 SchedulingContext ctxt, long idleWaitTime, long dbRetryInterval) 176 throws SchedulerException { 177 this.resources = resources; 178 try { 179 bind(); 180 } catch (Exception re) { 181 throw new SchedulerException( 182 "Unable to bind scheduler to RMI Registry.", re); 183 } 184 185 if (resources.getJMXExport()) { 186 try { 187 registerJMX(); 188 } catch (Exception e) { 189 throw new SchedulerException( 190 "Unable to register scheduler with MBeanServer.", e); 191 } 192 } 193 194 this.schedThread = new QuartzSchedulerThread(this, resources, ctxt); 195 if (idleWaitTime > 0) { 196 this.schedThread.setIdleWaitTime(idleWaitTime); 197 } 198 if (dbRetryInterval > 0) { 199 this.schedThread.setDbFailureRetryInterval(dbRetryInterval); 200 } 201 202 jobMgr = new ExecutingJobsManager(); 203 addGlobalJobListener(jobMgr); 204 errLogger = new ErrorLogger(); 205 addSchedulerListener(errLogger); 206 207 signaler = new SchedulerSignalerImpl(this); 208 209 getLog().info("Quartz Scheduler v." + getVersion() + " created."); 210 } 211 212 219 220 public String getVersion() { 221 return getVersionMajor() + "." + getVersionMinor() + "." 222 + getVersionIteration(); 223 } 224 225 public static String getVersionMajor() { 226 return VERSION_MAJOR; 227 } 228 229 public static String getVersionMinor() { 230 return VERSION_MINOR; 231 } 232 233 public static String getVersionIteration() { 234 return VERSION_ITERATION; 235 } 236 237 public SchedulerSignaler getSchedulerSignaler() { 238 return signaler; 239 } 240 241 public Log getLog() { 242 return log; 243 } 244 245 248 private void registerJMX() throws Exception { 249 org.apache.commons.modeler.Registry registry = 250 org.apache.commons.modeler.Registry.getRegistry(null, null); 251 252 String jmxObjectName = resources.getJMXObjectName(); 253 254 registry.registerComponent(this, jmxObjectName, null); 255 256 getLog().info("Scheduler registered with local MBeanServer under name '" + jmxObjectName + "'"); 257 } 258 259 262 private void unregisterJMX() throws Exception { 263 org.apache.commons.modeler.Registry registry = 264 org.apache.commons.modeler.Registry.getRegistry(null, null); 265 266 String jmxObjectName = resources.getJMXObjectName(); 267 268 registry.unregisterComponent(jmxObjectName); 269 270 getLog().info("Scheduler unregistered from name '" + jmxObjectName + "' in the local MBeanServer."); 271 } 272 273 278 private void bind() throws RemoteException { 279 String host = resources.getRMIRegistryHost(); 280 if (host == null || host.length() == 0) { 282 return; 283 } 284 285 RemotableQuartzScheduler exportable = null; 286 287 if(resources.getRMIServerPort() > 0) { 288 exportable = (RemotableQuartzScheduler) UnicastRemoteObject 289 .exportObject(this, resources.getRMIServerPort()); 290 } else { 291 exportable = (RemotableQuartzScheduler) UnicastRemoteObject 292 .exportObject(this); 293 } 294 295 Registry registry = null; 296 297 if (resources.getRMICreateRegistryStrategy().equals( 298 QuartzSchedulerResources.CREATE_REGISTRY_AS_NEEDED)) { 299 try { 300 registry = LocateRegistry.getRegistry(resources 306 .getRMIRegistryPort()); 307 registry.list(); 308 } catch (Exception e) { 309 registry = LocateRegistry.createRegistry(resources 310 .getRMIRegistryPort()); 311 } 312 } else if (resources.getRMICreateRegistryStrategy().equals( 313 QuartzSchedulerResources.CREATE_REGISTRY_ALWAYS)) { 314 try { 315 registry = LocateRegistry.createRegistry(resources 316 .getRMIRegistryPort()); 317 } catch (Exception e) { 318 registry = LocateRegistry.getRegistry(resources 324 .getRMIRegistryPort()); 325 } 326 } else { 327 registry = LocateRegistry.getRegistry(resources 328 .getRMIRegistryHost(), resources.getRMIRegistryPort()); 329 } 330 331 String bindName = resources.getRMIBindName(); 332 333 registry.rebind(bindName, exportable); 334 335 getLog().info("Scheduler bound to RMI registry under name '" + bindName + "'"); 336 } 337 338 343 private void unBind() throws RemoteException { 344 String host = resources.getRMIRegistryHost(); 345 if (host == null || host.length() == 0) { 347 return; 348 } 349 350 Registry registry = LocateRegistry.getRegistry(resources 351 .getRMIRegistryHost(), resources.getRMIRegistryPort()); 352 353 String bindName = resources.getRMIBindName(); 354 355 try { 356 registry.unbind(bindName); 357 UnicastRemoteObject.unexportObject(this, true); 358 } catch (java.rmi.NotBoundException nbe) { 359 } 360 361 getLog().info("Scheduler un-bound from name '" + bindName + "' in RMI registry"); 362 } 363 364 369 public String getSchedulerName() { 370 return resources.getName(); 371 } 372 373 378 public String getSchedulerInstanceId() { 379 return resources.getInstanceId(); 380 } 381 382 387 public ThreadGroup getSchedulerThreadGroup() { 388 if (threadGroup == null) { 389 threadGroup = new ThreadGroup ("QuartzScheduler:" 390 + getSchedulerName()); 391 if (resources.getMakeSchedulerThreadDaemon()) { 392 threadGroup.setDaemon(true); 393 } 394 } 395 396 return threadGroup; 397 } 398 399 public void addNoGCObject(Object obj) { 400 holdToPreventGC.add(obj); 401 } 402 403 public boolean removeNoGCObject(Object obj) { 404 return holdToPreventGC.remove(obj); 405 } 406 407 412 public SchedulerContext getSchedulerContext() throws SchedulerException { 413 return context; 414 } 415 416 public boolean isSignalOnSchedulingChange() { 417 return signalOnSchedulingChange; 418 } 419 420 public void setSignalOnSchedulingChange(boolean signalOnSchedulingChange) { 421 this.signalOnSchedulingChange = signalOnSchedulingChange; 422 } 423 424 430 440 public void start() throws SchedulerException { 441 442 if (closed) { 443 throw new SchedulerException( 444 "The Scheduler cannot be restarted after shutdown() has been called."); 445 } 446 447 if (initialStart == null) { 448 initialStart = new Date (); 449 this.resources.getJobStore().schedulerStarted(); 450 startPlugins(); 451 } 452 453 schedThread.togglePause(false); 454 455 getLog().info( 456 "Scheduler " + resources.getUniqueIdentifier() + " started."); 457 } 458 459 468 public void standby() { 469 schedThread.togglePause(true); 470 getLog().info( 471 "Scheduler " + resources.getUniqueIdentifier() + " paused."); 472 } 473 474 479 public boolean isInStandbyMode() { 480 return schedThread.isPaused(); 481 } 482 483 public Date runningSince() { 484 return initialStart; 485 } 486 487 public int numJobsExecuted() { 488 return jobMgr.getNumJobsFired(); 489 } 490 491 public Class getJobStoreClass() { 492 return resources.getJobStore().getClass(); 493 } 494 495 public boolean supportsPersistence() { 496 return resources.getJobStore().supportsPersistence(); 497 } 498 499 public Class getThreadPoolClass() { 500 return resources.getThreadPool().getClass(); 501 } 502 503 public int getThreadPoolSize() { 504 return resources.getThreadPool().getPoolSize(); 505 } 506 507 518 public void shutdown() { 519 shutdown(false); 520 } 521 522 536 public void shutdown(boolean waitForJobsToComplete) { 537 538 if(closed == true) { 539 return; 540 } 541 542 getLog().info( 543 "Scheduler " + resources.getUniqueIdentifier() 544 + " shutting down."); 545 standby(); 546 547 closed = true; 548 549 schedThread.halt(); 550 551 resources.getThreadPool().shutdown(waitForJobsToComplete); 552 553 if (waitForJobsToComplete) { 554 while (jobMgr.getNumJobsCurrentlyExecuting() > 0) { 555 try { 556 Thread.sleep(100); 557 } catch (Exception ignore) { 558 } 559 } 560 } 561 562 try { 566 schedThread.join(); 567 } catch (InterruptedException ignore) { 568 } 569 570 resources.getJobStore().shutdown(); 571 572 notifySchedulerListenersShutdown(); 573 574 shutdownPlugins(); 575 576 SchedulerRepository.getInstance().remove(resources.getName()); 577 578 holdToPreventGC.clear(); 579 580 try { 581 unBind(); 582 } catch (RemoteException re) { 583 } 584 585 if (resources.getJMXExport()) { 586 try { 587 unregisterJMX(); 588 } catch (Exception e) { 589 } 590 } 591 592 getLog().info( 593 "Scheduler " + resources.getUniqueIdentifier() 594 + " shutdown complete."); 595 } 596 597 602 public boolean isShutdown() { 603 return closed; 604 } 605 606 public void validateState() throws SchedulerException { 607 if (isShutdown()) { 608 throw new SchedulerException("The Scheduler has been shutdown."); 609 } 610 611 } 613 614 631 public List getCurrentlyExecutingJobs() { 632 return jobMgr.getExecutingJobs(); 633 } 634 635 641 657 public Date scheduleJob(SchedulingContext ctxt, JobDetail jobDetail, 658 Trigger trigger) throws SchedulerException { 659 validateState(); 660 661 if (jobDetail == null) { 662 throw new SchedulerException("JobDetail cannot be null", 663 SchedulerException.ERR_CLIENT_ERROR); 664 } 665 666 if (trigger == null) { 667 throw new SchedulerException("Trigger cannot be null", 668 SchedulerException.ERR_CLIENT_ERROR); 669 } 670 671 jobDetail.validate(); 672 673 if (trigger.getJobName() == null) { 674 trigger.setJobName(jobDetail.getName()); 675 trigger.setJobGroup(jobDetail.getGroup()); 676 } else if (trigger.getJobName() != null 677 && !trigger.getJobName().equals(jobDetail.getName())) { 678 throw new SchedulerException( 679 "Trigger does not reference given job!", 680 SchedulerException.ERR_CLIENT_ERROR); 681 } else if (trigger.getJobGroup() != null 682 && !trigger.getJobGroup().equals(jobDetail.getGroup())) { 683 throw new SchedulerException( 684 "Trigger does not reference given job!", 685 SchedulerException.ERR_CLIENT_ERROR); 686 } 687 688 trigger.validate(); 689 690 Calendar cal = null; 691 if (trigger.getCalendarName() != null) { 692 cal = resources.getJobStore().retrieveCalendar(ctxt, 693 trigger.getCalendarName()); 694 } 695 Date ft = trigger.computeFirstFireTime(cal); 696 697 if (ft == null) { 698 throw new SchedulerException( 699 "Based on configured schedule, the given trigger will never fire.", 700 SchedulerException.ERR_CLIENT_ERROR); 701 } 702 703 resources.getJobStore().storeJobAndTrigger(ctxt, jobDetail, trigger); 704 notifySchedulerThread(); 705 notifySchedulerListenersSchduled(trigger); 706 707 return ft; 708 } 709 710 721 public Date scheduleJob(SchedulingContext ctxt, Trigger trigger) 722 throws SchedulerException { 723 validateState(); 724 725 if (trigger == null) { 726 throw new SchedulerException("Trigger cannot be null", 727 SchedulerException.ERR_CLIENT_ERROR); 728 } 729 730 trigger.validate(); 731 732 Calendar cal = null; 733 if (trigger.getCalendarName() != null) { 734 cal = resources.getJobStore().retrieveCalendar(ctxt, 735 trigger.getCalendarName()); 736 if(cal == null) { 737 throw new SchedulerException( 738 "Calendar not found: " + trigger.getCalendarName(), 739 SchedulerException.ERR_PERSISTENCE_CALENDAR_DOES_NOT_EXIST); 740 } 741 } 742 Date ft = trigger.computeFirstFireTime(cal); 743 744 if (ft == null) { 745 throw new SchedulerException( 746 "Based on configured schedule, the given trigger will never fire.", 747 SchedulerException.ERR_CLIENT_ERROR); 748 } 749 750 resources.getJobStore().storeTrigger(ctxt, trigger, false); 751 notifySchedulerThread(); 752 notifySchedulerListenersSchduled(trigger); 753 754 return ft; 755 } 756 757 775 public void addJob(SchedulingContext ctxt, JobDetail jobDetail, 776 boolean replace) throws SchedulerException { 777 validateState(); 778 779 if (!jobDetail.isDurable() && !replace) { 780 throw new SchedulerException( 781 "Jobs added with no trigger must be durable.", 782 SchedulerException.ERR_CLIENT_ERROR); 783 } 784 785 resources.getJobStore().storeJob(ctxt, jobDetail, replace); 786 } 787 788 798 public boolean deleteJob(SchedulingContext ctxt, String jobName, 799 String groupName) throws SchedulerException { 800 validateState(); 801 802 if(groupName == null) { 803 groupName = Scheduler.DEFAULT_GROUP; 804 } 805 806 return resources.getJobStore().removeJob(ctxt, jobName, groupName); 807 } 808 809 815 public boolean unscheduleJob(SchedulingContext ctxt, String triggerName, 816 String groupName) throws SchedulerException { 817 validateState(); 818 819 if(groupName == null) { 820 groupName = Scheduler.DEFAULT_GROUP; 821 } 822 823 if (resources.getJobStore().removeTrigger(ctxt, triggerName, groupName)) { 824 notifySchedulerThread(); 825 notifySchedulerListenersUnschduled(triggerName, groupName); 826 } else { 827 return false; 828 } 829 830 return true; 831 } 832 833 834 851 public Date rescheduleJob(SchedulingContext ctxt, String triggerName, 852 String groupName, Trigger newTrigger) throws SchedulerException { 853 validateState(); 854 855 if(groupName == null) { 856 groupName = Scheduler.DEFAULT_GROUP; 857 } 858 859 newTrigger.validate(); 860 861 Calendar cal = null; 862 if (newTrigger.getCalendarName() != null) { 863 cal = resources.getJobStore().retrieveCalendar(ctxt, 864 newTrigger.getCalendarName()); 865 } 866 Date ft = newTrigger.computeFirstFireTime(cal); 867 868 if (ft == null) { 869 throw new SchedulerException( 870 "Based on configured schedule, the given trigger will never fire.", 871 SchedulerException.ERR_CLIENT_ERROR); 872 } 873 874 if (resources.getJobStore().replaceTrigger(ctxt, triggerName, groupName, newTrigger)) { 875 notifySchedulerThread(); 876 notifySchedulerListenersUnschduled(triggerName, groupName); 877 notifySchedulerListenersSchduled(newTrigger); 878 } else { 879 return null; 880 } 881 882 return ft; 883 884 } 885 886 887 private String newTriggerId() { 888 long r = random.nextLong(); 889 if (r < 0) { 890 r = -r; 891 } 892 return "MT_" 893 + Long.toString(r, 30 + (int) (System.currentTimeMillis() % 7)); 894 } 895 896 902 public void triggerJob(SchedulingContext ctxt, String jobName, 903 String groupName, JobDataMap data) throws SchedulerException { 904 validateState(); 905 906 if(groupName == null) { 907 groupName = Scheduler.DEFAULT_GROUP; 908 } 909 910 Trigger trig = new org.quartz.SimpleTrigger(newTriggerId(), 911 Scheduler.DEFAULT_MANUAL_TRIGGERS, jobName, groupName, 912 new Date (), null, 0, 0); 913 trig.setVolatility(false); 914 trig.computeFirstFireTime(null); 915 if(data != null) { 916 trig.setJobDataMap(data); 917 } 918 919 boolean collision = true; 920 while (collision) { 921 try { 922 resources.getJobStore().storeTrigger(ctxt, trig, false); 923 collision = false; 924 } catch (ObjectAlreadyExistsException oaee) { 925 trig.setName(newTriggerId()); 926 } 927 } 928 929 notifySchedulerThread(); 930 notifySchedulerListenersSchduled(trig); 931 } 932 933 939 public void triggerJobWithVolatileTrigger(SchedulingContext ctxt, 940 String jobName, String groupName, JobDataMap data) throws SchedulerException { 941 validateState(); 942 943 if(groupName == null) { 944 groupName = Scheduler.DEFAULT_GROUP; 945 } 946 947 Trigger trig = new org.quartz.SimpleTrigger(newTriggerId(), 948 Scheduler.DEFAULT_MANUAL_TRIGGERS, jobName, groupName, 949 new Date (), null, 0, 0); 950 trig.setVolatility(true); 951 trig.computeFirstFireTime(null); 952 if(data != null) { 953 trig.setJobDataMap(data); 954 } 955 956 boolean collision = true; 957 while (collision) { 958 try { 959 resources.getJobStore().storeTrigger(ctxt, trig, false); 960 collision = false; 961 } catch (ObjectAlreadyExistsException oaee) { 962 trig.setName(newTriggerId()); 963 } 964 } 965 966 notifySchedulerThread(); 967 notifySchedulerListenersSchduled(trig); 968 } 969 970 976 public void pauseTrigger(SchedulingContext ctxt, String triggerName, 977 String groupName) throws SchedulerException { 978 validateState(); 979 980 if(groupName == null) { 981 groupName = Scheduler.DEFAULT_GROUP; 982 } 983 984 resources.getJobStore().pauseTrigger(ctxt, triggerName, groupName); 985 notifySchedulerThread(); 986 notifySchedulerListenersPausedTrigger(triggerName, groupName); 987 } 988 989 995 public void pauseTriggerGroup(SchedulingContext ctxt, String groupName) 996 throws SchedulerException { 997 validateState(); 998 999 if(groupName == null) { 1000 groupName = Scheduler.DEFAULT_GROUP; 1001 } 1002 1003 resources.getJobStore().pauseTriggerGroup(ctxt, groupName); 1004 notifySchedulerThread(); 1005 notifySchedulerListenersPausedTrigger(null, groupName); 1006 } 1007 1008 1015 public void pauseJob(SchedulingContext ctxt, String jobName, 1016 String groupName) throws SchedulerException { 1017 validateState(); 1018 1019 if(groupName == null) { 1020 groupName = Scheduler.DEFAULT_GROUP; 1021 } 1022 1023 resources.getJobStore().pauseJob(ctxt, jobName, groupName); 1024 notifySchedulerThread(); 1025 notifySchedulerListenersPausedJob(jobName, groupName); 1026 } 1027 1028 1035 public void pauseJobGroup(SchedulingContext ctxt, String groupName) 1036 throws SchedulerException { 1037 validateState(); 1038 1039 if(groupName == null) { 1040 groupName = Scheduler.DEFAULT_GROUP; 1041 } 1042 1043 resources.getJobStore().pauseJobGroup(ctxt, groupName); 1044 notifySchedulerThread(); 1045 notifySchedulerListenersPausedJob(null, groupName); 1046 } 1047 1048 1060 public void resumeTrigger(SchedulingContext ctxt, String triggerName, 1061 String groupName) throws SchedulerException { 1062 validateState(); 1063 1064 if(groupName == null) { 1065 groupName = Scheduler.DEFAULT_GROUP; 1066 } 1067 1068 resources.getJobStore().resumeTrigger(ctxt, triggerName, groupName); 1069 notifySchedulerThread(); 1070 notifySchedulerListenersResumedTrigger(triggerName, groupName); 1071 } 1072 1073 1085 public void resumeTriggerGroup(SchedulingContext ctxt, String groupName) 1086 throws SchedulerException { 1087 validateState(); 1088 1089 if(groupName == null) { 1090 groupName = Scheduler.DEFAULT_GROUP; 1091 } 1092 1093 resources.getJobStore().resumeTriggerGroup(ctxt, groupName); 1094 notifySchedulerThread(); 1095 notifySchedulerListenersResumedTrigger(null, groupName); 1096 } 1097 1098 public Set getPausedTriggerGroups(SchedulingContext ctxt) throws SchedulerException { 1099 return resources.getJobStore().getPausedTriggerGroups(ctxt); 1100 } 1101 1102 1115 public void resumeJob(SchedulingContext ctxt, String jobName, 1116 String groupName) throws SchedulerException { 1117 validateState(); 1118 1119 if(groupName == null) { 1120 groupName = Scheduler.DEFAULT_GROUP; 1121 } 1122 1123 resources.getJobStore().resumeJob(ctxt, jobName, groupName); 1124 notifySchedulerThread(); 1125 notifySchedulerListenersResumedJob(jobName, groupName); 1126 } 1127 1128 1141 public void resumeJobGroup(SchedulingContext ctxt, String groupName) 1142 throws SchedulerException { 1143 validateState(); 1144 1145 if(groupName == null) { 1146 groupName = Scheduler.DEFAULT_GROUP; 1147 } 1148 1149 resources.getJobStore().resumeJobGroup(ctxt, groupName); 1150 notifySchedulerThread(); 1151 notifySchedulerListenersResumedJob(null, groupName); 1152 } 1153 1154 1169 public void pauseAll(SchedulingContext ctxt) throws SchedulerException { 1170 validateState(); 1171 1172 resources.getJobStore().pauseAll(ctxt); 1173 notifySchedulerThread(); 1174 notifySchedulerListenersPausedTrigger(null, null); 1175 } 1176 1177 1190 public void resumeAll(SchedulingContext ctxt) throws SchedulerException { 1191 validateState(); 1192 1193 resources.getJobStore().resumeAll(ctxt); 1194 notifySchedulerThread(); 1195 notifySchedulerListenersResumedTrigger(null, null); 1196 } 1197 1198 1203 public String [] getJobGroupNames(SchedulingContext ctxt) 1204 throws SchedulerException { 1205 validateState(); 1206 1207 return resources.getJobStore().getJobGroupNames(ctxt); 1208 } 1209 1210 1216 public String [] getJobNames(SchedulingContext ctxt, String groupName) 1217 throws SchedulerException { 1218 validateState(); 1219 1220 if(groupName == null) { 1221 groupName = Scheduler.DEFAULT_GROUP; 1222 } 1223 1224 return resources.getJobStore().getJobNames(ctxt, groupName); 1225 } 1226 1227 1233 public Trigger[] getTriggersOfJob(SchedulingContext ctxt, String jobName, 1234 String groupName) throws SchedulerException { 1235 validateState(); 1236 1237 if(groupName == null) { 1238 groupName = Scheduler.DEFAULT_GROUP; 1239 } 1240 1241 return resources.getJobStore().getTriggersForJob(ctxt, jobName, 1242 groupName); 1243 } 1244 1245 1251 public String [] getTriggerGroupNames(SchedulingContext ctxt) 1252 throws SchedulerException { 1253 validateState(); 1254 1255 return resources.getJobStore().getTriggerGroupNames(ctxt); 1256 } 1257 1258 1264 public String [] getTriggerNames(SchedulingContext ctxt, String groupName) 1265 throws SchedulerException { 1266 validateState(); 1267 1268 if(groupName == null) { 1269 groupName = Scheduler.DEFAULT_GROUP; 1270 } 1271 1272 return resources.getJobStore().getTriggerNames(ctxt, groupName); 1273 } 1274 1275 1281 public JobDetail getJobDetail(SchedulingContext ctxt, String jobName, 1282 String jobGroup) throws SchedulerException { 1283 validateState(); 1284 1285 if(jobGroup == null) { 1286 jobGroup = Scheduler.DEFAULT_GROUP; 1287 } 1288 1289 return resources.getJobStore().retrieveJob(ctxt, jobName, jobGroup); 1290 } 1291 1292 1298 public Trigger getTrigger(SchedulingContext ctxt, String triggerName, 1299 String triggerGroup) throws SchedulerException { 1300 validateState(); 1301 1302 if(triggerGroup == null) { 1303 triggerGroup = Scheduler.DEFAULT_GROUP; 1304 } 1305 1306 return resources.getJobStore().retrieveTrigger(ctxt, triggerName, 1307 triggerGroup); 1308 } 1309 1310 1320 public int getTriggerState(SchedulingContext ctxt, String triggerName, 1321 String triggerGroup) throws SchedulerException { 1322 validateState(); 1323 1324 if(triggerGroup == null) { 1325 triggerGroup = Scheduler.DEFAULT_GROUP; 1326 } 1327 1328 return resources.getJobStore().getTriggerState(ctxt, triggerName, 1329 triggerGroup); 1330 } 1331 1332 1342 public void addCalendar(SchedulingContext ctxt, String calName, 1343 Calendar calendar, boolean replace, boolean updateTriggers) throws SchedulerException { 1344 validateState(); 1345 1346 resources.getJobStore().storeCalendar(ctxt, calName, calendar, replace, updateTriggers); 1347 } 1348 1349 1358 public boolean deleteCalendar(SchedulingContext ctxt, String calName) 1359 throws SchedulerException { 1360 validateState(); 1361 1362 return resources.getJobStore().removeCalendar(ctxt, calName); 1363 } 1364 1365 1370 public Calendar getCalendar(SchedulingContext ctxt, String calName) 1371 throws SchedulerException { 1372 validateState(); 1373 1374 return resources.getJobStore().retrieveCalendar(ctxt, calName); 1375 } 1376 1377 1382 public String [] getCalendarNames(SchedulingContext ctxt) 1383 throws SchedulerException { 1384 validateState(); 1385 1386 return resources.getJobStore().getCalendarNames(ctxt); 1387 } 1388 1389 1400 public void addGlobalJobListener(JobListener jobListener) { 1401 if (jobListener.getName() == null 1402 || jobListener.getName().length() == 0) { 1403 throw new IllegalArgumentException ( 1404 "JobListener name cannot be empty."); 1405 } 1406 1407 synchronized (globalJobListeners) { 1408 globalJobListeners.put(jobListener.getName(), jobListener); 1409 } 1410 } 1411 1412 1417 public void addJobListener(JobListener jobListener) { 1418 if (jobListener.getName() == null 1419 || jobListener.getName().length() == 0) { 1420 throw new IllegalArgumentException ( 1421 "JobListener name cannot be empty."); 1422 } 1423 1424 synchronized (jobListeners) { 1425 jobListeners.put(jobListener.getName(), jobListener); 1426 } 1427 } 1428 1429 1440 public boolean removeGlobalJobListener(JobListener jobListener) { 1441 return removeGlobalJobListener((jobListener == null) ? null : jobListener.getName()); 1442 } 1443 1444 1453 public boolean removeGlobalJobListener(String name) { 1454 synchronized (globalJobListeners) { 1455 return (globalJobListeners.remove(name) != null); 1456 } 1457 } 1458 1459 1468 public boolean removeJobListener(String name) { 1469 synchronized (jobListeners) { 1470 return (jobListeners.remove(name) != null); 1471 } 1472 } 1473 1474 1480 public List getGlobalJobListeners() { 1481 synchronized (globalJobListeners) { 1482 return new LinkedList (globalJobListeners.values()); 1483 } 1484 } 1485 1486 1492 public Set getJobListenerNames() { 1493 synchronized (jobListeners) { 1494 return new HashSet (jobListeners.keySet()); 1495 } 1496 } 1497 1498 1504 public JobListener getGlobalJobListener(String name) { 1505 synchronized (globalJobListeners) { 1506 return (JobListener)globalJobListeners.get(name); 1507 } 1508 } 1509 1510 1516 public JobListener getJobListener(String name) { 1517 synchronized (jobListeners) { 1518 return (JobListener) jobListeners.get(name); 1519 } 1520 } 1521 1522 1533 public void addGlobalTriggerListener(TriggerListener triggerListener) { 1534 if (triggerListener.getName() == null 1535 || triggerListener.getName().length() == 0) { 1536 throw new IllegalArgumentException ( 1537 "TriggerListener name cannot be empty."); 1538 } 1539 1540 synchronized (globalTriggerListeners) { 1541 globalTriggerListeners.put(triggerListener.getName(), triggerListener); 1542 } 1543 } 1544 1545 1550 public void addTriggerListener(TriggerListener triggerListener) { 1551 if (triggerListener.getName() == null 1552 || triggerListener.getName().length() == 0) { 1553 throw new IllegalArgumentException ( 1554 "TriggerListener name cannot be empty."); 1555 } 1556 1557 synchronized (triggerListeners) { 1558 triggerListeners.put(triggerListener.getName(), triggerListener); 1559 } 1560 } 1561 1562 1573 public boolean removeGlobalTriggerListener(TriggerListener triggerListener) { 1574 return removeGlobalTriggerListener((triggerListener == null) ? null : triggerListener.getName()); 1575 } 1576 1577 1586 public boolean removeGlobalTriggerListener(String name) { 1587 synchronized (globalTriggerListeners) { 1588 return (globalTriggerListeners.remove(name) != null); 1589 } 1590 } 1591 1592 1601 public boolean removeTriggerListener(String name) { 1602 synchronized (triggerListeners) { 1603 return (triggerListeners.remove(name) != null); 1604 } 1605 } 1606 1607 1613 public List getGlobalTriggerListeners() { 1614 synchronized (globalTriggerListeners) { 1615 return new LinkedList (globalTriggerListeners.values()); 1616 } 1617 } 1618 1619 1625 public Set getTriggerListenerNames() { 1626 synchronized (triggerListeners) { 1627 return new HashSet (triggerListeners.keySet()); 1628 } 1629 } 1630 1631 1637 public TriggerListener getGlobalTriggerListener(String name) { 1638 synchronized (globalTriggerListeners) { 1639 return (TriggerListener)globalTriggerListeners.get(name); 1640 } 1641 } 1642 1643 1649 public TriggerListener getTriggerListener(String name) { 1650 synchronized (triggerListeners) { 1651 return (TriggerListener) triggerListeners.get(name); 1652 } 1653 } 1654 1655 1661 public void addSchedulerListener(SchedulerListener schedulerListener) { 1662 synchronized (schedulerListeners) { 1663 schedulerListeners.add(schedulerListener); 1664 } 1665 } 1666 1667 1676 public boolean removeSchedulerListener(SchedulerListener schedulerListener) { 1677 synchronized (schedulerListeners) { 1678 return schedulerListeners.remove(schedulerListener); 1679 } 1680 } 1681 1682 1688 public List getSchedulerListeners() { 1689 synchronized (schedulerListeners) { 1690 return (List )schedulerListeners.clone(); 1691 } 1692 } 1693 1694 protected void notifyJobStoreJobComplete(SchedulingContext ctxt, 1695 Trigger trigger, JobDetail detail, int instCode) 1696 throws JobPersistenceException { 1697 1698 resources.getJobStore().triggeredJobComplete(ctxt, trigger, detail, 1699 instCode); 1700 } 1701 1702 protected void notifyJobStoreJobVetoed(SchedulingContext ctxt, 1703 Trigger trigger, JobDetail detail, int instCode) 1704 throws JobPersistenceException { 1705 1706 resources.getJobStore().triggeredJobComplete(ctxt, trigger, detail, instCode); 1707 } 1708 1709 protected void notifySchedulerThread() { 1710 if (isSignalOnSchedulingChange()) { 1711 schedThread.signalSchedulingChange(); 1712 } 1713 } 1714 1715 private List buildTriggerListenerList(String [] additionalLstnrs) 1716 throws SchedulerException { 1717 List triggerListeners = getGlobalTriggerListeners(); 1718 for (int i = 0; i < additionalLstnrs.length; i++) { 1719 TriggerListener tl = getTriggerListener(additionalLstnrs[i]); 1720 1721 if (tl != null) { 1722 triggerListeners.add(tl); 1723 } else { 1724 throw new SchedulerException("TriggerListener '" 1725 + additionalLstnrs[i] + "' not found.", 1726 SchedulerException.ERR_TRIGGER_LISTENER_NOT_FOUND); 1727 } 1728 } 1729 1730 return triggerListeners; 1731 } 1732 1733 private List buildJobListenerList(String [] additionalLstnrs) 1734 throws SchedulerException { 1735 List jobListeners = getGlobalJobListeners(); 1736 for (int i = 0; i < additionalLstnrs.length; i++) { 1737 JobListener jl = getJobListener(additionalLstnrs[i]); 1738 1739 if (jl != null) { 1740 jobListeners.add(jl); 1741 } else { 1742 throw new SchedulerException("JobListener '" 1743 + additionalLstnrs[i] + "' not found.", 1744 SchedulerException.ERR_JOB_LISTENER_NOT_FOUND); 1745 } 1746 } 1747 1748 return jobListeners; 1749 } 1750 1751 public boolean notifyTriggerListenersFired(JobExecutionContext jec) 1752 throws SchedulerException { 1753 List triggerListeners = buildTriggerListenerList(jec.getTrigger() 1755 .getTriggerListenerNames()); 1756 1757 boolean vetoedExecution = false; 1758 1759 java.util.Iterator itr = triggerListeners.iterator(); 1761 while (itr.hasNext()) { 1762 TriggerListener tl = (TriggerListener) itr.next(); 1763 try { 1764 tl.triggerFired(jec.getTrigger(), jec); 1765 1766 if(tl.vetoJobExecution(jec.getTrigger(), jec)) { 1767 vetoedExecution = true; 1768 } 1769 } catch (Exception e) { 1770 SchedulerException se = new SchedulerException( 1771 "TriggerListener '" + tl.getName() 1772 + "' threw exception: " + e.getMessage(), e); 1773 se.setErrorCode(SchedulerException.ERR_TRIGGER_LISTENER); 1774 throw se; 1775 } 1776 } 1777 1778 return vetoedExecution; 1779 } 1780 1781 1782 public void notifyTriggerListenersMisfired(Trigger trigger) 1783 throws SchedulerException { 1784 List triggerListeners = buildTriggerListenerList(trigger 1786 .getTriggerListenerNames()); 1787 1788 java.util.Iterator itr = triggerListeners.iterator(); 1790 while (itr.hasNext()) { 1791 TriggerListener tl = (TriggerListener) itr.next(); 1792 try { 1793 tl.triggerMisfired(trigger); 1794 } catch (Exception e) { 1795 SchedulerException se = new SchedulerException( 1796 "TriggerListener '" + tl.getName() 1797 + "' threw exception: " + e.getMessage(), e); 1798 se.setErrorCode(SchedulerException.ERR_TRIGGER_LISTENER); 1799 throw se; 1800 } 1801 } 1802 } 1803 1804 public void notifyTriggerListenersComplete(JobExecutionContext jec, 1805 int instCode) throws SchedulerException { 1806 List triggerListeners = buildTriggerListenerList(jec.getTrigger() 1808 .getTriggerListenerNames()); 1809 1810 java.util.Iterator itr = triggerListeners.iterator(); 1812 while (itr.hasNext()) { 1813 TriggerListener tl = (TriggerListener) itr.next(); 1814 try { 1815 tl.triggerComplete(jec.getTrigger(), jec, instCode); 1816 } catch (Exception e) { 1817 SchedulerException se = new SchedulerException( 1818 "TriggerListener '" + tl.getName() 1819 + "' threw exception: " + e.getMessage(), e); 1820 se.setErrorCode(SchedulerException.ERR_TRIGGER_LISTENER); 1821 throw se; 1822 } 1823 } 1824 } 1825 1826 public void notifyJobListenersToBeExecuted(JobExecutionContext jec) 1827 throws SchedulerException { 1828 List jobListeners = buildJobListenerList(jec.getJobDetail() 1830 .getJobListenerNames()); 1831 1832 java.util.Iterator itr = jobListeners.iterator(); 1834 while (itr.hasNext()) { 1835 JobListener jl = (JobListener) itr.next(); 1836 try { 1837 jl.jobToBeExecuted(jec); 1838 } catch (Exception e) { 1839 SchedulerException se = new SchedulerException( 1840 "JobListener '" + jl.getName() + "' threw exception: " 1841 + e.getMessage(), e); 1842 se.setErrorCode(SchedulerException.ERR_JOB_LISTENER); 1843 throw se; 1844 } 1845 } 1846 } 1847 1848 public void notifyJobListenersWasVetoed(JobExecutionContext jec) 1849 throws SchedulerException { 1850 List jobListeners = buildJobListenerList(jec.getJobDetail() 1852 .getJobListenerNames()); 1853 1854 java.util.Iterator itr = jobListeners.iterator(); 1856 while (itr.hasNext()) { 1857 JobListener jl = (JobListener) itr.next(); 1858 try { 1859 jl.jobExecutionVetoed(jec); 1860 } catch (Exception e) { 1861 SchedulerException se = new SchedulerException( 1862 "JobListener '" + jl.getName() + "' threw exception: " 1863 + e.getMessage(), e); 1864 se.setErrorCode(SchedulerException.ERR_JOB_LISTENER); 1865 throw se; 1866 } 1867 } 1868 } 1869 1870 public void notifyJobListenersWasExecuted(JobExecutionContext jec, 1871 JobExecutionException je) throws SchedulerException { 1872 List jobListeners = buildJobListenerList(jec.getJobDetail() 1874 .getJobListenerNames()); 1875 1876 java.util.Iterator itr = jobListeners.iterator(); 1878 while (itr.hasNext()) { 1879 JobListener jl = (JobListener) itr.next(); 1880 try { 1881 jl.jobWasExecuted(jec, je); 1882 } catch (Exception e) { 1883 SchedulerException se = new SchedulerException( 1884 "JobListener '" + jl.getName() + "' threw exception: " 1885 + e.getMessage(), e); 1886 se.setErrorCode(SchedulerException.ERR_JOB_LISTENER); 1887 throw se; 1888 } 1889 } 1890 } 1891 1892 public void notifySchedulerListenersError(String msg, SchedulerException se) { 1893 List schedListeners = getSchedulerListeners(); 1895 1896 java.util.Iterator itr = schedListeners.iterator(); 1898 while (itr.hasNext()) { 1899 SchedulerListener sl = (SchedulerListener) itr.next(); 1900 try { 1901 sl.schedulerError(msg, se); 1902 } catch (Exception e) { 1903 getLog() 1904 .error( 1905 "Error while notifying SchedulerListener of error: ", 1906 e); 1907 getLog().error( 1908 " Original error (for notification) was: " + msg, se); 1909 } 1910 } 1911 } 1912 1913 public void notifySchedulerListenersSchduled(Trigger trigger) { 1914 List schedListeners = getSchedulerListeners(); 1916 1917 java.util.Iterator itr = schedListeners.iterator(); 1919 while (itr.hasNext()) { 1920 SchedulerListener sl = (SchedulerListener) itr.next(); 1921 try { 1922 sl.jobScheduled(trigger); 1923 } catch (Exception e) { 1924 getLog().error( 1925 "Error while notifying SchedulerListener of scheduled job." 1926 + " Triger=" + trigger.getFullName(), e); 1927 } 1928 } 1929 } 1930 1931 public void notifySchedulerListenersUnschduled(String triggerName, 1932 String triggerGroup) { 1933 List schedListeners = getSchedulerListeners(); 1935 1936 java.util.Iterator itr = schedListeners.iterator(); 1938 while (itr.hasNext()) { 1939 SchedulerListener sl = (SchedulerListener) itr.next(); 1940 try { 1941 sl.jobUnscheduled(triggerName, triggerGroup); 1942 } catch (Exception e) { 1943 getLog().error( 1944 "Error while notifying SchedulerListener of unscheduled job." 1945 + " Triger=" + triggerGroup + "." 1946 + triggerName, e); 1947 } 1948 } 1949 } 1950 1951 public void notifySchedulerListenersFinalized(Trigger trigger) { 1952 List schedListeners = getSchedulerListeners(); 1954 1955 java.util.Iterator itr = schedListeners.iterator(); 1957 while (itr.hasNext()) { 1958 SchedulerListener sl = (SchedulerListener) itr.next(); 1959 try { 1960 sl.triggerFinalized(trigger); 1961 } catch (Exception e) { 1962 getLog().error( 1963 "Error while notifying SchedulerListener of finalized trigger." 1964 + " Triger=" + trigger.getFullName(), e); 1965 } 1966 } 1967 } 1968 1969 public void notifySchedulerListenersPausedTrigger(String name, String group) { 1970 List schedListeners = getSchedulerListeners(); 1972 1973 java.util.Iterator itr = schedListeners.iterator(); 1975 while (itr.hasNext()) { 1976 SchedulerListener sl = (SchedulerListener) itr.next(); 1977 try { 1978 sl.triggersPaused(name, group); 1979 } catch (Exception e) { 1980 getLog().error( 1981 "Error while notifying SchedulerListener of paused trigger/group." 1982 + " Triger=" + group + "." + name, e); 1983 } 1984 } 1985 } 1986 1987 public void notifySchedulerListenersResumedTrigger(String name, String group) { 1988 List schedListeners = getSchedulerListeners(); 1990 1991 java.util.Iterator itr = schedListeners.iterator(); 1993 while (itr.hasNext()) { 1994 SchedulerListener sl = (SchedulerListener) itr.next(); 1995 try { 1996 sl.triggersResumed(name, group); 1997 } catch (Exception e) { 1998 getLog().error( 1999 "Error while notifying SchedulerListener of resumed trigger/group." 2000 + " Triger=" + group + "." + name, e); 2001 } 2002 } 2003 } 2004 2005 public void notifySchedulerListenersPausedJob(String name, String group) { 2006 List schedListeners = getSchedulerListeners(); 2008 2009 java.util.Iterator itr = schedListeners.iterator(); 2011 while (itr.hasNext()) { 2012 SchedulerListener sl = (SchedulerListener) itr.next(); 2013 try { 2014 sl.jobsPaused(name, group); 2015 } catch (Exception e) { 2016 getLog().error( 2017 "Error while notifying SchedulerListener of paused job/group." 2018 + " Job=" + group + "." + name, e); 2019 } 2020 } 2021 } 2022 2023 public void notifySchedulerListenersResumedJob(String name, String group) { 2024 List schedListeners = getSchedulerListeners(); 2026 2027 java.util.Iterator itr = schedListeners.iterator(); 2029 while (itr.hasNext()) { 2030 SchedulerListener sl = (SchedulerListener) itr.next(); 2031 try { 2032 sl.jobsResumed(name, group); 2033 } catch (Exception e) { 2034 getLog().error( 2035 "Error while notifying SchedulerListener of resumed job/group." 2036 + " Job=" + group + "." + name, e); 2037 } 2038 } 2039 } 2040 2041 public void notifySchedulerListenersShutdown() { 2042 List schedListeners = getSchedulerListeners(); 2044 2045 java.util.Iterator itr = schedListeners.iterator(); 2047 while (itr.hasNext()) { 2048 SchedulerListener sl = (SchedulerListener) itr.next(); 2049 try { 2050 sl.schedulerShutdown(); 2051 } catch (Exception e) { 2052 getLog().error( 2053 "Error while notifying SchedulerListener of shutdown.", 2054 e); 2055 } 2056 } 2057 } 2058 2059 public void setJobFactory(JobFactory factory) throws SchedulerException { 2060 2061 if(factory == null) { 2062 throw new IllegalArgumentException ("JobFactory cannot be set to null!"); 2063 } 2064 2065 getLog().info("JobFactory set to: " + factory); 2066 2067 this.jobFactory = factory; 2068 } 2069 2070 public JobFactory getJobFactory() { 2071 return jobFactory; 2072 } 2073 2074 2075 2087 public boolean interrupt(SchedulingContext ctxt, String jobName, String groupName) throws UnableToInterruptJobException { 2088 2089 if(groupName == null) { 2090 groupName = Scheduler.DEFAULT_GROUP; 2091 } 2092 2093 List jobs = getCurrentlyExecutingJobs(); 2094 java.util.Iterator it = jobs.iterator(); 2095 2096 JobExecutionContext jec = null; 2097 JobDetail jobDetail = null; 2098 Job job = null; 2099 2100 boolean interrupted = false; 2101 2102 while (it.hasNext()) { 2103 jec = (JobExecutionContext)it.next(); 2104 jobDetail = jec.getJobDetail(); 2105 if (jobName.equals(jobDetail.getName()) 2106 && groupName.equals(jobDetail.getGroup())){ 2107 job = jec.getJobInstance(); 2108 if (job instanceof InterruptableJob) { 2109 ((InterruptableJob)job).interrupt(); 2110 interrupted = true; 2111 } else { 2112 throw new UnableToInterruptJobException( 2113 "Job '" 2114 + jobName 2115 + "' of group '" 2116 + groupName 2117 + "' can not be interrupted, since it does not implement " 2118 + InterruptableJob.class.getName()); 2119 2120 } 2121 } 2122 } 2123 2124 return interrupted; 2125 } 2126 2127 private void shutdownPlugins() { 2128 java.util.Iterator itr = resources.getSchedulerPlugins().iterator(); 2129 while (itr.hasNext()) { 2130 SchedulerPlugin plugin = (SchedulerPlugin) itr.next(); 2131 plugin.shutdown(); 2132 } 2133 } 2134 2135 private void startPlugins() { 2136 java.util.Iterator itr = resources.getSchedulerPlugins().iterator(); 2137 while (itr.hasNext()) { 2138 SchedulerPlugin plugin = (SchedulerPlugin) itr.next(); 2139 plugin.start(); 2140 } 2141 } 2142 2143} 2144 2145 2151class ErrorLogger extends SchedulerListenerSupport { 2152 ErrorLogger() { 2153 } 2154 2155 public void schedulerError(String msg, SchedulerException cause) { 2156 getLog().error(msg, cause); 2157 } 2158} 2159 2160 2166class ExecutingJobsManager implements JobListener { 2167 HashMap executingJobs = new HashMap (); 2168 2169 int numJobsFired = 0; 2170 2171 ExecutingJobsManager() { 2172 } 2173 2174 public String getName() { 2175 return getClass().getName(); 2176 } 2177 2178 public int getNumJobsCurrentlyExecuting() { 2179 synchronized (executingJobs) { 2180 return executingJobs.size(); 2181 } 2182 } 2183 2184 public void jobToBeExecuted(JobExecutionContext context) { 2185 numJobsFired++; 2186 2187 synchronized (executingJobs) { 2188 executingJobs 2189 .put(context.getTrigger().getFireInstanceId(), context); 2190 } 2191 } 2192 2193 public void jobWasExecuted(JobExecutionContext context, 2194 JobExecutionException jobException) { 2195 synchronized (executingJobs) { 2196 executingJobs.remove(context.getTrigger().getFireInstanceId()); 2197 } 2198 } 2199 2200 public int getNumJobsFired() { 2201 return numJobsFired; 2202 } 2203 2204 public List getExecutingJobs() { 2205 synchronized (executingJobs) { 2206 return java.util.Collections.unmodifiableList(new ArrayList ( 2207 executingJobs.values())); 2208 } 2209 } 2210 2211 public void jobExecutionVetoed(JobExecutionContext context) { 2212 2213 } 2214} 2215 | Popular Tags |