/** * '$RCSfile$' * Purpose: A Class that handles scheduling tasks * Copyright: 2009 Regents of the University of California and the * National Center for Ecological Analysis and Synthesis * Authors: Michael Daigle * * '$Author: daigle $' * '$Date: 2009-03-25 13:41:15 -0800 (Wed, 25 Mar 2009) $' * '$Revision: 4861 $' * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package edu.ucsb.nceas.metacat.scheduler; import java.io.PrintWriter; import java.util.Calendar; import java.util.HashMap; import java.util.Vector; import org.apache.log4j.Logger; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleTrigger; import org.quartz.Trigger; import org.quartz.TriggerUtils; import edu.ucsb.nceas.metacat.shared.AccessException; import edu.ucsb.nceas.metacat.shared.BaseService; import edu.ucsb.nceas.metacat.shared.ServiceException; import edu.ucsb.nceas.utilities.DateUtil; import edu.ucsb.nceas.utilities.StatusUtil; import edu.ucsb.nceas.utilities.UtilException; public class SchedulerService extends BaseService { private static SchedulerService schedulerService = null; private static Logger logMetacat = Logger.getLogger(SchedulerService.class); private static Scheduler sched = null; /** * private constructor since this is a singleton */ private SchedulerService() throws ServiceException { start(); } /** * Get the single instance of SchedulerService. * * @return the single instance of SchedulerService */ public static SchedulerService getInstance() throws ServiceException { if (schedulerService == null) { schedulerService = new SchedulerService(); } return schedulerService; } // this is a refreshable class public boolean refreshable() { return true; } // do the refresh public void doRefresh() throws ServiceException { stop(); start(); } // initialize the service public void start() throws ServiceException { try { // get the Quartz scheduler factory SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory(); // get the scheduler sched = schedFact.getScheduler(); sched.start(); // get all existing jobs from the database ScheduledJobAccess jobAccess = new ScheduledJobAccess(); HashMap allJobsMap = jobAccess.getAllJobs(null); // reschedule each job that is in a SCHEDULED state. for (Long jobId : allJobsMap.keySet()) { ScheduledJobDAO jobDAO = allJobsMap.get(jobId); String[] groups = {"scheduler_group"}; if (jobDAO.getStatus().equals(StatusUtil.SCHEDULED)) { // send false as the last param so the reschedule method will not // complain that the job is already in a SCHEDULED state. rescheduleJob(jobDAO, "scheduler_user", groups, false); } } } catch (AccessException ae) { throw new ServiceException("SchedulerService.start - DB Access issue when starting scheduler: ", ae); } catch (SchedulerException se) { throw new ServiceException("SchedulerService.start - Scheduler engine issue when starting scheduler: " + se.getMessage()); } } // Stop the scheduler public void stop() throws ServiceException { try { sched.shutdown(); sched = null; } catch (SchedulerException se) { throw new ServiceException("SchedulerService.stop - Could not shut down scheduler: " + se.getMessage()); } } // this will eventually return the scheduler status protected Vector getStatus() throws ServiceException { return new Vector(); } /** * Schedule a job * * @param jobDAO * the job data object to schedule * @param username * the user that we will use to schedule * @param groups * the user group that we will use to schedule * @return a message saying that the job was scheduled */ public String scheduleJob(ScheduledJobDAO jobDAO, String username, String[] groups) throws ServiceException { // convert the start time to a calendar object Calendar startTimeCal = Calendar.getInstance(); startTimeCal.setTime(jobDAO.getStartTime()); // convert the start time to a calendar object Calendar endTimeCal = Calendar.getInstance(); endTimeCal.setTime(jobDAO.getEndTime()); // extract the job parameters from their data objects and put into a string map HashMap jobParams = new HashMap(); HashMap jobParamDAOs = jobDAO.getAllJobParams(); for (String paramName : jobParamDAOs.keySet()) { jobParams.put(paramName, jobParamDAOs.get(paramName).getValue()); } // schedule the job return scheduleJob(jobDAO.getName(), startTimeCal, endTimeCal, jobDAO.getIntervalValue(), jobDAO.getIntervalUnit(), jobDAO.getClassName(), jobDAO.getGroupName(), jobParams); } /** * schedule a job * * @param jobName * the name of the job * @param startCal * a calendar holding the start date of the job * @param endCal * a calendar holding the end date of the job * @param intervalValue * the run interval for the job * @param intervalUnit * the unit of the run interval for the job * @param jobClassName * the job class name * @param jobGroup * the job group name * @param jobParams * a map of additional job parameters * @param username * the user name * @param groups * the user's group name * @return a message saying that the job was scheduled */ @SuppressWarnings("unchecked") public String scheduleJob(String jobName, Calendar startCal, Calendar endCal, int intervalValue, String intervalUnit, String jobClassName, String jobGroup, HashMap jobParams) throws ServiceException { Class jobClass = null; try { jobClass = (Class) Class.forName(jobClassName); String startTimeStr = DateUtil.getHumanReadable(startCal); logMetacat.info("SchedulerService.scheduleJob - Scheduling job -- name: " + jobName + ", class: " + jobClassName + ", start time: " + startTimeStr + ", interval value: " + intervalValue + ", interval unit: " + intervalUnit); // start the job in the job scheduler startJob(jobName, startCal, endCal, intervalValue, intervalUnit, jobClass, jobGroup, jobParams); // get a database access object and create the job in the database ScheduledJobAccess jobAccess = new ScheduledJobAccess(); jobAccess.createJob(jobName, jobName, jobGroup, jobClass, startCal, endCal, intervalValue, intervalUnit, jobParams); } catch (AccessException ae) { try { deleteJob(jobName); } catch (Exception e) { // Not much we can do here but log this logMetacat.error("SchedulerService.scheduleJob - An access exception was thrown when writing job: " + jobName + "to the db, and another exception was thrown when trying to remove the " + "job from the scheduler. The db and scheduler may be out of sync: " + e.getMessage()); } throw new ServiceException("SchedulerService.scheduleJob - Error accessing db: ", ae); } catch (ClassNotFoundException cnfe) { throw new ServiceException("SchedulerService.scheduleJob - Could not find class with name: " + jobClassName + " : " + cnfe.getMessage()); } catch (UtilException ue) { throw new ServiceException("SchedulerService.scheduleJob - Could not schedule " + "job due to a utility issue: " + ue.getMessage()); } return "Scheduled: " + jobName; } /** * schedule a job one time with a given delay. The job is registered in the * scheduler, but not persisted to the database. The delay is calculated * from the time that this method is called. * * @param jobName * the name of the job * @param delay * the delay in seconds, minutes, hours or days from the time * this method is called (i.e. 30s, 5m, 2h, 1d) * @param jobClassName * the job class name * @param jobGroup * the job group name * @param jobParams * a map of additional job parameters * @param username * the user name * @param groups * the user's group name * @return a message saying that the job was scheduled */ @SuppressWarnings("unchecked") public String scheduleDelayedJob(String jobName, String delay, String jobClassName, String jobGroup, HashMap jobParams, String username, String[] groups) throws ServiceException { Class jobClass = null; try { jobClass = (Class) Class.forName(jobClassName); Calendar startCal = getStartDateFromDelay(delay); logMetacat.info("SchedulerService.scheduleDelayedJob - Scheduling job -- name: " + jobName + ", delay: " + delay + ", job class name: " + jobClassName); // start the job in the job scheduler startOneTimeJob(jobName, startCal, jobClass, jobGroup, jobParams); } catch (ClassNotFoundException cnfe) { throw new ServiceException("SchedulerService.scheduleJob - Could not find class with name: " + jobClassName + " : " + cnfe.getMessage()); } return "Scheduled: " + jobName; } /** * Unschedule a job. This removed it from the scheduler in memory and * changed it's status to unscheduled in the database. * * @param jobName * the name of the job to unschedule * @param username * the user name * @param groups * the user's group name * @return a message saying the job was unscheduled */ public String unscheduleJob(String jobName, String username, String[] groups) throws ServiceException { ScheduledJobDAO jobDAO = null; try { ScheduledJobAccess jobAccess = new ScheduledJobAccess(); jobDAO = jobAccess.getJobByName(jobName); if (jobDAO == null) { throw new ServiceException("SchedulerService.unscheduleJob - Could " + "not find job with name: " + jobName); } // remove the job from the scheduler sched.deleteJob(jobDAO.getName(), jobDAO.getGroupName()); // change the status of the job to unscheduled in the database. jobDAO.setStatus(StatusUtil.UNSCHEDULED); jobAccess.updateJobStatus(jobDAO); } catch (SchedulerException se) { throw new ServiceException("SchedulerService.unscheduleJob - Could not create " + "scheduled job because of service issue: " + se.getMessage()); } catch (AccessException ae) { throw new ServiceException("SchedulerService.unscheduleJob - Could not create " + "scheduled job : " + jobDAO.getName() + " because of db access issue: ", ae); } return "Unscheduled: " + jobName; } /** * Reschedule a job. This call will always check to make sure the status is not SCHEDULED * @param jobDAO the job data object holding the information about the job to reschedule * @param username * the user name * @param groups * the user's group name * @return a message saying that the job was rescheduled */ public String rescheduleJob(ScheduledJobDAO jobDAO, String username, String[] groups) throws ServiceException { return rescheduleJob(jobDAO, username, groups, true); } /** * Reschedule a job. * * @param jobDAO * the job data object holding the information about the job to * reschedule * @param username * the user name * @param groups * the user's group name * @param checkStatus * if set to true, the method will check to make sure the status * is UNSCHEDULED before restarting. Otherwise, the method will * not check. This is so that we can restart a service at startup * that was running when metacat was shut down. * @return a message saying that the job was rescheduled */ @SuppressWarnings("unchecked") public String rescheduleJob(ScheduledJobDAO jobDAO, String username, String[] groups, boolean checkStatus) throws ServiceException { try { ScheduledJobAccess jobAccess = new ScheduledJobAccess(); if (jobDAO == null) { throw new ServiceException("SchedulerService.reScheduleJob - Cannot reschedule nonexistant job."); } // if we are checking status, make sure the job is in an UNSCHEDULED state in the db if (checkStatus && !jobDAO.getStatus().equals(StatusUtil.UNSCHEDULED)) { throw new ServiceException("SchedulerService.reScheduleJob - Cannot reschedule a job with status: " + jobDAO.getStatus() + ". Status must be 'unscheduled'."); } Calendar startCal = Calendar.getInstance(); startCal.setTime(jobDAO.getStartTime()); Calendar endCal = Calendar.getInstance(); endCal.setTime(jobDAO.getEndTime()); HashMap jobParams = new HashMap(); HashMap jobParamDAOs = jobDAO.getAllJobParams(); for (String paramName : jobParamDAOs.keySet()) { jobParams.put(paramName, jobParamDAOs.get(paramName).getValue()); } Class jobClass = null; String jobClassName = jobDAO.getClassName(); try { jobClass = (Class)Class.forName(jobClassName); } catch (ClassNotFoundException cnfe) { throw new ServiceException("SchedulerService.scheduleJob - Could not find class with name: " + jobDAO.getClassName() + " : " + cnfe.getMessage()); } String startTimeStr = DateUtil.getHumanReadable(startCal); logMetacat.info("SchedulerService.rescheduleJob - name: " + jobDAO.getName() + ", class: " + jobClassName + ", start time: " + startTimeStr + ", interval value: " + jobDAO.getIntervalValue() + ", interval unit: " + jobDAO.getIntervalUnit()); // start the job in the scheduler startJob(jobDAO.getName(), startCal, endCal, jobDAO.getIntervalValue(), jobDAO.getIntervalUnit(), jobClass, jobDAO.getGroupName(), jobParams); // update the status in the database jobDAO.setStatus(StatusUtil.SCHEDULED); jobAccess.updateJobStatus(jobDAO); } catch (AccessException ae) { throw new ServiceException("SchedulerService.reScheduleJob - Could not reschedule " + "job : " + jobDAO.getName() + " because of db access issue: ", ae); } catch (UtilException ue) { throw new ServiceException("SchedulerService.reScheduleJob - Could not reschedule " + "job : " + jobDAO.getName() + " due to a utility issue: " + ue.getMessage()); } return "Rescheduled: " + jobDAO.getName(); } /** * Remove the job from the scheduler and set the job status to deleted in the database * @param jobName * the string holding the name of the job to delete * @param username * the user name * @param groups * the user's group name * @return a message saying that the job was deleted */ public String deleteJob(String jobName) throws ServiceException { ScheduledJobDAO jobDAO = null; try { ScheduledJobAccess jobAccess = new ScheduledJobAccess(); jobDAO = jobAccess.getJobByName(jobName); } catch (AccessException ae) { throw new ServiceException("SchedulerService.deleteJob - Could not delete " + "scheduled job : " + jobDAO.getName() + " because of db access issue: ", ae); } return deleteJob(jobDAO); } /** * Remove the job from the scheduler and set the job status to deleted in the database * @param jobDAO * the job data object holding the information about the job to delete * @param username * the user name * @param groups * the user's group name * @return a message saying that the job was deleted */ public String deleteJob(ScheduledJobDAO jobDAO) throws ServiceException { String groupName = ""; try { sched.deleteJob(jobDAO.getName(), groupName); jobDAO.setStatus(StatusUtil.DELETED); ScheduledJobAccess jobAccess = new ScheduledJobAccess(); jobAccess.updateJobStatus(jobDAO); } catch (SchedulerException se) { throw new ServiceException("SchedulerService.deleteJob - Could not delete job: " + jobDAO.getName() + " for group: " + groupName + " : " + se.getMessage()); } catch (AccessException ae) { throw new ServiceException("SchedulerService.deleteJob - Could not delete " + "scheduled job: " + jobDAO.getName() + " because of db access issue: ", ae); } return "Deleted: " + jobDAO.getName(); } /** * Get information about the job in XML format * * @param jobId * the job for which we want the information * @return an XML representation of the job */ public String getJobInfoXML(Long jobId) throws ServiceException { String jobInfoXML = ""; try { ScheduledJobAccess jobAccess = new ScheduledJobAccess(); ScheduledJobDAO scheduledJobDAO = jobAccess.getJob(jobId); jobInfoXML += "" + jobToXML(scheduledJobDAO) + ""; } catch (AccessException ae) { throw new ServiceException("SchedulerService.getJobInfoXML - Could not get job info for job: " + jobId, ae); } return jobInfoXML; } /** * Get the information for jobs in a group in an xml format. A parameter * key/value pair can be provided as well to limit the jobs returned. * * @param groupName * the job group that we are searching for * @param paramName * the parameter name that we are looking for. this is ignored if * null * @param paramValue * the parameter value that we are looking for. this is ignored * if null * @return an XML representation of the jobs. */ public String getJobsInfoXML(String groupName, String paramName, String paramValue) throws ServiceException { String jobInfoXML = ""; try { ScheduledJobAccess jobAccess = new ScheduledJobAccess(); HashMap JobDAOMap = jobAccess.getJobsWithParameter(groupName, paramName, paramValue); jobInfoXML += ""; for (Long jobDAOId : JobDAOMap.keySet()) { ScheduledJobDAO jobDAO = JobDAOMap.get(jobDAOId); if (paramValue != null && paramName != null) { ScheduledJobParamDAO jobParamDAO = jobDAO.getJobParam(paramName); if(jobParamDAO != null && jobParamDAO.getValue().equals(paramValue)) { jobInfoXML += jobToXML(JobDAOMap.get(jobDAOId)); } } } jobInfoXML += ""; } catch (AccessException ae) { throw new ServiceException("SchedulerService.getJobInfoXML - Could not get jobs info for group: " + groupName, ae); } return jobInfoXML; } /** * Get the information for jobs in a group in an xml format. A parameter * key/value pair can be provided as well to limit the jobs returned. * * @param groupName * the job group that we are searching for * @param paramName * the parameter name that we are looking for. this is ignored if * null * @param paramValue * the parameter value that we are looking for. this is ignored * if null * @return an XML representation of the jobs. */ public void getJobsInfoXML(String groupName, String paramName, String paramValue, PrintWriter pw) throws ServiceException { try { ScheduledJobAccess jobAccess = new ScheduledJobAccess(); HashMap JobDAOMap = jobAccess.getJobsWithParameter(groupName, paramName, paramValue); pw.print(""); for (Long jobDAOId : JobDAOMap.keySet()) { ScheduledJobDAO jobDAO = JobDAOMap.get(jobDAOId); if (paramValue != null && paramName != null) { ScheduledJobParamDAO jobParamDAO = jobDAO.getJobParam(paramName); if(jobParamDAO != null && jobParamDAO.getValue().equals(paramValue)) { pw.print(jobToXML(JobDAOMap.get(jobDAOId))); } } } pw.print(""); } catch (AccessException ae) { throw new ServiceException("SchedulerService.getJobInfoXML - Could not get jobs info for group: " + groupName, ae); } } /** * Convert a single job to XML * @param scheduledJobDAO the job we want to convert * @return an XML representation of the job */ public String jobToXML(ScheduledJobDAO scheduledJobDAO) throws ServiceException { String jobXML = ""; if (scheduledJobDAO != null) { jobXML += ""; jobXML += "" + scheduledJobDAO.getId() + ""; jobXML += "" + scheduledJobDAO.getCreateTime() + ""; jobXML += "" + scheduledJobDAO.getModTime() + ""; jobXML += "" + scheduledJobDAO.getStatus() + ""; jobXML += "" + scheduledJobDAO.getName() + ""; jobXML += "" + scheduledJobDAO.getName() + ""; jobXML += "" + scheduledJobDAO.getGroupName() + ""; jobXML += "" + scheduledJobDAO.getClassName() + ""; String startTimeString = null; try { startTimeString = DateUtil.getHumanReadable(scheduledJobDAO.getStartTime()); } catch (UtilException ue) { throw new ServiceException("SchedulerService.jobToXML - error getting human readable date for job: " + scheduledJobDAO.getId() + " ; " + ue.getMessage()); } jobXML += "" + startTimeString + ""; String endTimeString = null; try { if (scheduledJobDAO.getEndTime() != null) { endTimeString = DateUtil.getHumanReadable(scheduledJobDAO.getEndTime()); } } catch (UtilException ue) { throw new ServiceException("SchedulerService.jobToXML - error getting human readable date for job: " + scheduledJobDAO.getId() + " ; " + ue.getMessage()); } jobXML += "" + endTimeString + ""; jobXML += "" + scheduledJobDAO.getIntervalValue() + ""; jobXML += "" + scheduledJobDAO.getIntervalUnit() + ""; HashMap jobParams = scheduledJobDAO .getAllJobParams(); for (String jobParamKey : jobParams.keySet()) { jobXML += ""; jobXML += "" + jobParams.get(jobParamKey).getId() + ""; jobXML += "" + jobParams.get(jobParamKey).getCreateTime() + ""; jobXML += "" + jobParams.get(jobParamKey).getModTime() + ""; jobXML += "" + jobParams.get(jobParamKey).getStatus() + ""; jobXML += "" + jobParams.get(jobParamKey).getJobId() + ""; jobXML += "" + jobParams.get(jobParamKey).getKey() + ""; jobXML += "" + jobParams.get(jobParamKey).getValue() + ""; jobXML += ""; } jobXML += ""; } return jobXML; } /** * Start a job in the scheduler * * @param jobName * the name of the job * @param startCal * a calendar holding the start date of the job * @param intervalValue * the run interval for the job * @param intervalUnit * the unit of the run interval for the job * @param jobClassName * the job class name * @param jobGroup * the job group name * @param jobParams * a map of additional job parameters * @param username * the user name * @param groups * the user's group name */ private void startJob(String jobName, Calendar startCal, Calendar endCal, int intervalValue, String intervalUnit, Class jobClass, String jobGroup, HashMap jobParams) throws ServiceException { JobDetail jobDetail = new JobDetail(jobName, jobGroup, jobClass); jobDetail.setJobDataMap(new JobDataMap(jobParams)); // call the appropriate scheduling method depending on the schedule interval unit if (intervalUnit.equals("sec")) { scheduleSecondlyJob(jobName, jobClass, startCal, endCal, intervalValue, jobGroup, jobDetail); } else if (intervalUnit.equals("min")) { scheduleMinutelyJob(jobName, jobClass, startCal, endCal, intervalValue, jobGroup, jobDetail); } else if (intervalUnit.equals("hour")) { scheduleHourlyJob(jobName, jobClass, startCal, endCal, intervalValue, jobGroup, jobDetail); } else if (intervalUnit.equals("day")) { scheduleDailyJob(jobName, jobClass, startCal, endCal, intervalValue, jobGroup, jobDetail); } else if (intervalUnit.equals("week")) { scheduleWeeklyJob(jobName, jobClass, startCal, endCal, intervalValue, jobGroup, jobDetail); } else if (intervalUnit.equals("mon")) { scheduleMonthlyJob(jobName, jobClass, startCal, endCal, intervalValue, jobGroup, jobDetail); } else { throw new ServiceException("SchedulerService.scheduleJob - Could not interpret interval unit: " + intervalUnit + ". Unit must be sec, min, hour, day, week or mon"); } } /** * Schedule a job in the scheduler that has an interval based in seconds * * @param jobName * the name of the job * @param jobClass * the job class object * @param startTime * the time of the first run * @param jobGroup * the group of this job * @param jobDetail * the job detail object */ private void startOneTimeJob(String jobName, Calendar startTime, Class jobClass, String jobGroup, HashMap jobParams) throws ServiceException { JobDetail jobDetail = new JobDetail(jobName, jobGroup, jobClass); jobDetail.setJobDataMap(new JobDataMap(jobParams)); SimpleTrigger trigger = new SimpleTrigger(); trigger.setName(jobName); trigger.setStartTime(startTime.getTime()); trigger.setRepeatCount(1); try { sched.scheduleJob(jobDetail, trigger); } catch (SchedulerException se) { throw new ServiceException("SchedulerService.scheduleSecondlyJob - Could not create " + "scheduler: " + se.getMessage()); } } /** * Schedule a job in the scheduler that has an interval based in seconds * * @param jobName * the name of the job * @param jobClass * the job class object * @param startTime * the time of the first run * @param interval * the interval in seconds between runs * @param jobGroup * the group of this job * @param jobDetail * the job detail object */ private void scheduleSecondlyJob(String jobName, Class jobClass, Calendar startTime, Calendar endTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException { Trigger trigger = TriggerUtils.makeSecondlyTrigger(interval); trigger.setName(jobName); trigger.setStartTime(startTime.getTime()); if (endTime != null) { trigger.setEndTime(endTime.getTime()); } try { sched.scheduleJob(jobDetail, trigger); } catch (SchedulerException se) { throw new ServiceException("SchedulerService.scheduleSecondlyJob - Could not create " + "scheduler: " + se.getMessage()); } } /** * Schedule a job in the scheduler that has an interval based in minutes * * @param jobName * the name of the job * @param jobClass * the job class object * @param startTime * the time of the first run * @param interval * the interval in minutes between runs * @param jobGroup * the group of this job * @param jobDetail * the job detail object */ private void scheduleMinutelyJob(String jobName, Class jobClass, Calendar startTime, Calendar endTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException { Trigger trigger = TriggerUtils.makeMinutelyTrigger(interval); trigger.setName(jobName); trigger.setStartTime(startTime.getTime()); if (endTime != null) { trigger.setEndTime(endTime.getTime()); } try { sched.scheduleJob(jobDetail, trigger); } catch (SchedulerException se) { throw new ServiceException("SchedulerService.scheduleMinutelyJob - Could not create " + "scheduler: " + se.getMessage()); } } /** * Schedule a job in the scheduler that has an interval based in hours * * @param jobName * the name of the job * @param jobClass * the job class object * @param startTime * the time of the first run * @param interval * the interval in hours between runs * @param jobGroup * the group of this job * @param jobDetail * the job detail object */ private void scheduleHourlyJob(String jobName, Class jobClass, Calendar startTime, Calendar endTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException { Trigger trigger = TriggerUtils.makeHourlyTrigger(interval); trigger.setName(jobName); trigger.setStartTime(startTime.getTime()); if (endTime != null) { trigger.setEndTime(endTime.getTime()); } try { sched.scheduleJob(jobDetail, trigger); } catch (SchedulerException se) { throw new ServiceException("SchedulerService.scheduleHourlyJob - Could not create " + "scheduler: " + se.getMessage()); } } /** * Schedule a job in the scheduler that has an interval based in days * * @param jobName * the name of the job * @param jobClass * the job class object * @param startTime * the time of the first run * @param interval * the interval in days between runs * @param jobGroup * the group of this job * @param jobDetail * the job detail object */ private void scheduleDailyJob(String jobName, Class jobClass, Calendar startTime, Calendar endTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException { Trigger trigger = TriggerUtils.makeDailyTrigger(startTime.get(Calendar.HOUR), startTime.get(Calendar.MINUTE)); trigger.setName(jobName); trigger.setStartTime(startTime.getTime()); if (endTime != null) { trigger.setEndTime(endTime.getTime()); } try { sched.scheduleJob(jobDetail, trigger); } catch (SchedulerException se) { throw new ServiceException("SchedulerService.scheduleHourlyJob - Could not create " + "scheduler: " + se.getMessage()); } } /** * Schedule a job in the scheduler that has an interval based in days * * @param jobName * the name of the job * @param jobClass * the job class object * @param startTime * the time of the first run * @param interval * the interval in days between runs * @param jobGroup * the group of this job * @param jobDetail * the job detail object */ private void scheduleWeeklyJob(String jobName, Class jobClass, Calendar startTime, Calendar endTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException { Trigger trigger = TriggerUtils.makeWeeklyTrigger(startTime.get(Calendar.DAY_OF_WEEK), startTime.get(Calendar.HOUR), startTime.get(Calendar.MINUTE)); trigger.setName(jobName); trigger.setStartTime(startTime.getTime()); if (endTime != null) { trigger.setEndTime(endTime.getTime()); } try { sched.scheduleJob(jobDetail, trigger); } catch (SchedulerException se) { throw new ServiceException("SchedulerService.scheduleHourlyJob - Could not create " + "scheduler: " + se.getMessage()); } } /** * Schedule a job in the scheduler that has an interval based in days * * @param jobName * the name of the job * @param jobClass * the job class object * @param startTime * the time of the first run * @param interval * the interval in days between runs * @param jobGroup * the group of this job * @param jobDetail * the job detail object */ private void scheduleMonthlyJob(String jobName, Class jobClass, Calendar startTime, Calendar endTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException { Trigger trigger = TriggerUtils.makeMonthlyTrigger(startTime.get(Calendar.DAY_OF_MONTH), startTime.get(Calendar.HOUR), startTime.get(Calendar.MINUTE)); trigger.setName(jobName); trigger.setStartTime(startTime.getTime()); if (endTime != null) { trigger.setEndTime(endTime.getTime()); } try { sched.scheduleJob(jobDetail, trigger); } catch (SchedulerException se) { throw new ServiceException("SchedulerService.scheduleHourlyJob - Could not create " + "scheduler: " + se.getMessage()); } } /** * Extract the start date from the delay value * * @param delay * a string representing the start delay in * notation where value is an integer and unit is one of s,m,h or * d * @return the calendar object holding the start date */ public Calendar getStartDateFromDelay(String delay) throws ServiceException { Calendar cal = Calendar.getInstance(); char delayUnit = delay.trim().charAt(delay.length() - 1); String delayStrValue = delay.trim().substring(0, delay.length() - 1); int delayValue; try { delayValue = Integer.parseInt(delayStrValue); } catch (NumberFormatException nfe) { throw new ServiceException("SchedulerService.getStartDateFromDelay - Could not " + "parse delay value into an integer: " + delayStrValue + " : " + nfe.getMessage()); } switch (delayUnit) { case 's': case 'S': cal.add(Calendar.SECOND, delayValue); break; case 'm': case 'M': cal.add(Calendar.MINUTE, delayValue); break; case 'h': case 'H': cal.add(Calendar.HOUR, delayValue); break; case 'd': case 'D': cal.add(Calendar.DAY_OF_YEAR, delayValue); break; default: throw new ServiceException("SchedulerService.getStartDateFromDelay - Could not " + "interpret delay unit: " + delayUnit + ". Unit must be s, m, h or d"); } return cal; } }