Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that handles scheduling tasks 
4
 *  Copyright: 2009 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Michael Daigle
7
 * 
8
 *   '$Author: daigle $'
9
 *     '$Date: 2009-03-25 13:41:15 -0800 (Wed, 25 Mar 2009) $'
10
 * '$Revision: 4861 $'
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 */
26

    
27
package edu.ucsb.nceas.metacat.scheduler;
28

    
29
import java.util.Calendar;
30
import java.util.HashMap;
31
import java.util.Vector;
32

    
33
import org.apache.log4j.Logger;
34

    
35
import org.quartz.Job;
36
import org.quartz.JobDataMap;
37
import org.quartz.JobDetail;
38
import org.quartz.Scheduler;
39
import org.quartz.SchedulerException;
40
import org.quartz.SchedulerFactory;
41
import org.quartz.Trigger;
42
import org.quartz.TriggerUtils;
43

    
44
import edu.ucsb.nceas.metacat.service.BaseService;
45
import edu.ucsb.nceas.metacat.service.ServiceException;
46
import edu.ucsb.nceas.shared.AccessException;
47
import edu.ucsb.nceas.utilities.DateUtil;
48
import edu.ucsb.nceas.utilities.StatusUtil;
49
import edu.ucsb.nceas.utilities.UtilException;
50

    
51
public class SchedulerService extends BaseService {
52
	
53
	private static SchedulerService schedulerService = null;
54
	
55
	private static Logger logMetacat = Logger.getLogger(SchedulerService.class);
56
	
57
	private static Scheduler sched = null;
58

    
59
	/**
60
	 * private constructor since this is a singleton
61
	 */
62
	private SchedulerService() throws ServiceException {
63
		start();
64
	}
65
	
66
	/**
67
	 * Get the single instance of SchedulerService.
68
	 * 
69
	 * @return the single instance of SchedulerService
70
	 */
71
	public static SchedulerService getInstance() throws ServiceException {
72
		if (schedulerService == null) {
73
			schedulerService = new SchedulerService();
74
		}
75
		return schedulerService;
76
	}
77
	
78
	// this is a refreshable class
79
	public boolean refreshable() {
80
		return true;
81
	}
82

    
83
	// do the refresh
84
	public void doRefresh() throws ServiceException {
85
		stop();
86
		start();
87
	}
88

    
89
	// initialize the service
90
	public void start() throws ServiceException {
91
		try {
92
			// get the Quartz scheduler factory
93
			SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
94
			
95
			// get the scheduler
96
			sched = schedFact.getScheduler();
97
			sched.start();
98
			
99
			// get all existing jobs from the database
100
			ScheduledJobAccess jobAccess = new ScheduledJobAccess();
101
			HashMap<Long, ScheduledJobDAO> allJobsMap = jobAccess.getAllJobs(null);
102
			
103
			// reschedule each job that is in a SCHEDULED state.  
104
			for (Long jobId : allJobsMap.keySet()) {
105
				ScheduledJobDAO jobDAO = allJobsMap.get(jobId);
106
				String[] groups = {"scheduler_group"};
107
				if (jobDAO.getStatus().equals(StatusUtil.SCHEDULED)) {
108
					// send false as the last param so the reschedule method will not 
109
					// complain that the job is already in a SCHEDULED state.
110
					rescheduleJob(jobDAO, "scheduler_user", groups, false);
111
				}
112
			}			
113
			
114
		} catch (AccessException ae) {
115
			throw new ServiceException("SchedulerService.start - DB Access issue when starting scheduler: ", ae);
116
		} catch (SchedulerException se) {
117
			throw new ServiceException("SchedulerService.start - Scheduler engine issue when starting scheduler: " + se.getMessage());
118
		}		
119
	}
120
	
121
	// Stop the scheduler
122
	public void stop() throws ServiceException {
123
		try {
124
			sched.shutdown(true);
125
			sched = null;
126
		} catch (SchedulerException se) {
127
			throw new ServiceException("SchedulerService.stop - Could not shut down scheduler: " + se.getMessage());
128
		}		
129
	}
130
	
131
	// this will eventually return the scheduler status
132
	protected Vector<String> getStatus() throws ServiceException {
133
		return new Vector<String>();
134
	}
135
	
136
	/**
137
	 * Schedule a job
138
	 * 
139
	 * @param jobDAO
140
	 *            the job data object to schedule
141
	 * @param username
142
	 *            the user that we will use to schedule
143
	 * @param groups
144
	 *            the user group that we will use to schedule
145
	 * @return a message saying that the job was scheduled
146
	 */
147
	public String scheduleJob(ScheduledJobDAO jobDAO, String username, String[] groups) throws ServiceException {
148
        
149
		// convert the start time to a calendar object
150
		Calendar startTimeCal = Calendar.getInstance();
151
        startTimeCal.setTime(jobDAO.getStartTime());
152
        
153
		// convert the start time to a calendar object
154
		Calendar endTimeCal = Calendar.getInstance();
155
        endTimeCal.setTime(jobDAO.getEndTime());
156
        
157
        // extract the job parameters from their data objects and put into a string map
158
        HashMap<String, String> jobParams = new HashMap<String, String>();
159
        HashMap<String, ScheduledJobParamDAO> jobParamDAOs = jobDAO.getAllJobParams();
160
        for (String paramName : jobParamDAOs.keySet()) {
161
        	jobParams.put(paramName, jobParamDAOs.get(paramName).getValue());   	
162
        }
163
        
164
        // schedule the job
165
		return scheduleJob(jobDAO.getName(), startTimeCal, endTimeCal, jobDAO.getIntervalValue(), 
166
				jobDAO.getIntervalUnit(), jobDAO.getClassName(), jobDAO.getGroupName(), 
167
				jobParams, username, groups);
168
	}
169
	
170
	/**
171
	 * schedule a job
172
	 * 
173
	 * @param jobName
174
	 *            the name of the job
175
	 * @param startCal
176
	 *            a calendar holding the start date of the job
177
	 * @param intervalValue
178
	 *            the run interval for the job
179
	 * @param intervalUnit
180
	 *            the unit of the run interval for the job
181
	 * @param jobClassName
182
	 *            the job class name
183
	 * @param jobGroup
184
	 *            the job group name
185
	 * @param jobParams
186
	 *            a map of additional job parameters
187
	 * @param username
188
	 *            the user name
189
	 * @param groups
190
	 *            the user's group name
191
	 * @return a message saying that the job was scheduled
192
	 */
193
	public String scheduleJob(String jobName, Calendar startCal, Calendar endCal, int intervalValue, 
194
			String intervalUnit, String jobClassName, String jobGroup, HashMap<String, String> jobParams, 
195
			String username, String[] groups) throws ServiceException {
196
        
197
        Class<Job> jobClass = null;
198
        try {
199
			jobClass = (Class<Job>) Class.forName(jobClassName);
200

    
201
			String startTimeStr = DateUtil.getHumanReadable(startCal, true);
202
			logMetacat.info("SchedulerService.scheduleJob - Scheduling job -- name: "
203
					+ jobName + ", class: " + jobClassName + ", start time: "
204
					+ startTimeStr + ", interval value: " + intervalValue
205
					+ ", interval unit: " + intervalUnit);
206

    
207
			// start the job in the job scheduler
208
			startJob(jobName, startCal, endCal, intervalValue, intervalUnit, jobClass, jobGroup,
209
					jobParams);
210

    
211
			// get a database access object and create the job in the database
212

    
213
			ScheduledJobAccess jobAccess = new ScheduledJobAccess();
214
			jobAccess.createJob(jobName, jobName, jobGroup, jobClass, startCal, endCal,
215
					intervalValue, intervalUnit, jobParams);
216
		} catch (AccessException ae) {
217
			try {
218
				deleteJob(jobName, username, groups);
219
			} catch (Exception e) {
220
				// Not much we can do here but log this
221
				logMetacat.error("SchedulerService.scheduleJob - An access exception was thrown when writing job: "
222
						+ jobName + "to the db, and another exception was thrown when trying to remove the "
223
						+ "job from the scheduler.  The db and scheduler may be out of sync: " + e.getMessage());
224
			}
225
			throw new ServiceException("SchedulerService.scheduleJob - Error accessing db: ", ae);
226
		} catch (ClassNotFoundException cnfe) {
227
			throw new ServiceException("SchedulerService.scheduleJob - Could not find class with name: "
228
							+ jobClassName + " : " + cnfe.getMessage());
229
		} catch (UtilException ue) {
230
			throw new ServiceException("SchedulerService.scheduleJob - Could not schedule "
231
							+ "job due to a utility issue: " + ue.getMessage());
232
		}
233
		
234
		return "Scheduled: " + jobName;
235
	}
236
	
237
	/**
238
	 * Unschedule a job. This removed it from the scheduler in memory and
239
	 * changed it's status to unscheduled in the database.
240
	 * 
241
	 * @param jobName
242
	 *            the name of the job to unschedule
243
	 * @param username
244
	 *            the user name
245
	 * @param groups
246
	 *            the user's group name
247
	 * @return a message saying the job was unscheduled
248
	 */
249
	public String unScheduleJob(String jobName, String username,
250
			String[] groups) throws ServiceException {
251
		try {
252
			ScheduledJobAccess jobAccess = new ScheduledJobAccess();
253
			ScheduledJobDAO jobDAO = jobAccess.getJobByName(jobName);
254
			if (jobDAO == null) {
255
				throw new ServiceException("SchedulerService.unscheduleJob - Could " 
256
						+ "not find job with name: " + jobName);
257
			}
258

    
259
			// remove the job from the scheduler
260
			sched.deleteJob(jobDAO.getName(), jobDAO.getGroupName());
261

    
262
			// change the status of the job to unscheduled in the database.
263
			jobDAO.setStatus(StatusUtil.UNSCHEDULED);
264
			jobAccess.updateJobStatus(jobDAO);
265
		} catch (SchedulerException se) {
266
			throw new ServiceException("SchedulerService.unscheduleJob - Could not create "
267
							+ "scheduled job because of service issue: " + se.getMessage());
268
		} catch (AccessException ae) {
269
			throw new ServiceException("SchedulerService.unscheduleJob - Could not create "
270
							+ "scheduled job because of db access issue: ", ae);
271
		}
272
		
273
		return "Unscheduled: " + jobName;
274
	}
275
	
276
	/**
277
	 * Reschedule a job. This call will always check to make sure the status is not SCHEDULED
278
	 * @param jobDAO the job data object holding the information about the job to reschedule
279
	 * @param username
280
	 *            the user name
281
	 * @param groups
282
	 *            the user's group name
283
	 * @return a message saying that the job was rescheduled
284
	 */
285
	public String rescheduleJob(ScheduledJobDAO jobDAO, String username, String[] groups) throws ServiceException {
286
		return rescheduleJob(jobDAO, username, groups, true);
287
	}
288
	
289
	/**
290
	 * Reschedule a job.
291
	 * 
292
	 * @param jobDAO
293
	 *            the job data object holding the information about the job to
294
	 *            reschedule
295
	 * @param username
296
	 *            the user name
297
	 * @param groups
298
	 *            the user's group name
299
	 * @param checkStatus
300
	 *            if set to true, the method will check to make sure the status
301
	 *            is UNSCHEDULED before restarting. Otherwise, the method will
302
	 *            not check. This is so that we can restart a service at startup
303
	 *            that was running when metacat was shut down.
304
	 * @return a message saying that the job was rescheduled
305
	 */
306
	public String rescheduleJob(ScheduledJobDAO jobDAO, String username, String[] groups, boolean checkStatus) throws ServiceException {
307
		
308
		try {
309
			ScheduledJobAccess jobAccess = new ScheduledJobAccess();
310
        
311
			if (jobDAO == null) {
312
				throw new ServiceException("SchedulerService.reScheduleJob - Cannot reschedule nonexistant job.");
313
			}
314
        
315
			// if we are checking status, make sure the job is in an UNSCHEDULED state in the db
316
			if (checkStatus && !jobDAO.getStatus().equals(StatusUtil.UNSCHEDULED)) {
317
				throw new ServiceException("SchedulerService.reScheduleJob - Cannot reschedule a job with status: " 
318
						+ jobDAO.getStatus() + ". Status must be 'unscheduled'.");
319
			}
320
        
321
			Calendar startCal = Calendar.getInstance();
322
	        startCal.setTime(jobDAO.getStartTime());
323
	        
324
			Calendar endCal = Calendar.getInstance();
325
	        endCal.setTime(jobDAO.getEndTime());
326
	        
327
	        HashMap<String, String> jobParams = new HashMap<String, String>();
328
	        HashMap<String, ScheduledJobParamDAO> jobParamDAOs = jobDAO.getAllJobParams();
329
	        for (String paramName : jobParamDAOs.keySet()) {
330
	        	jobParams.put(paramName, jobParamDAOs.get(paramName).getValue());   	
331
	        }
332
	        
333
	        Class<Job> jobClass = null;
334
	        String jobClassName = jobDAO.getClassName();
335
	        try {        	
336
	        	jobClass = (Class<Job>)Class.forName(jobClassName);     	
337
	        } catch (ClassNotFoundException cnfe) {
338
	        	throw new ServiceException("SchedulerService.scheduleJob - Could not find class with name: " 
339
	        			+ jobDAO.getClassName() + " : " + cnfe.getMessage());
340
	        } 
341
	        
342
	        String startTimeStr = DateUtil.getHumanReadable(startCal, true);
343
	        logMetacat.info("SchedulerService.rescheduleJob - name: " + jobDAO.getName() + ", class: " + jobClassName 
344
	        		+ ", start time: " + startTimeStr + ", interval value: " + jobDAO.getIntervalValue() 
345
	        		+ ", interval unit: " + jobDAO.getIntervalUnit());  
346
			
347
	        // start the job in the scheduler
348
			startJob(jobDAO.getName(), startCal, endCal, jobDAO.getIntervalValue(), jobDAO.getIntervalUnit(), jobClass, jobDAO.getGroupName(), jobParams);
349
	        
350
			// update the status in the database
351
			jobDAO.setStatus(StatusUtil.SCHEDULED);
352
			jobAccess.updateJobStatus(jobDAO);
353
			
354
		} catch (AccessException ae) {
355
			throw new ServiceException("SchedulerService.reScheduleJob - Could not reschedule "
356
					+ "job because of db access issue: ", ae);
357
		} catch (UtilException ue) {
358
			throw new ServiceException("SchedulerService.reScheduleJob - Could not reschedule "
359
					+ "job due to a utility issue: " + ue.getMessage());
360
		}
361
        		
362
		return "Resheduled: " + jobDAO.getName();
363
	}
364
	
365
	/**
366
	 * Remove the job from the scheduler and set the job status to deleted in the database
367
	 * @param jobDAO
368
	 *            the job data object holding the information about the job to
369
	 *            delete
370
	 * @param username
371
	 *            the user name
372
	 * @param groups
373
	 *            the user's group name
374
	 * @return a message saying that the job was deleted
375
	 */
376
	public String deleteJob(String jobName, String username,
377
			String[] groups) throws ServiceException {
378

    
379
		String groupName = "";
380
		try {
381
			ScheduledJobAccess jobAccess = new ScheduledJobAccess();
382
			ScheduledJobDAO jobDAO = jobAccess.getJobByName(jobName);
383
			groupName = jobDAO.getGroupName();
384

    
385
			sched.deleteJob(jobName, groupName);
386
			
387
			jobDAO.setStatus(StatusUtil.DELETED);
388
			jobAccess.updateJobStatus(jobDAO);
389
		} catch (SchedulerException se) {
390
			throw new ServiceException("SchedulerService.deleteJob - Could not delete job: " + jobName
391
							+ " for group: " + groupName + " : " + se.getMessage());
392
		} catch (AccessException ae) {
393
			throw new ServiceException("SchedulerService.deleteJob - Could not delete "
394
					+ "scheduled job because of db access issue: ", ae);
395
		}
396
		
397
		return "Deleted: " + jobName;
398
	}
399
	
400
	/**
401
	 * Get information about the job in XML format
402
	 * 
403
	 * @param jobId
404
	 *            the job for which we want the information
405
	 * @return an XML representation of the job
406
	 */
407
	public String getJobInfoXML(Long jobId) throws ServiceException {
408
		String jobInfoXML = "";
409
		
410
		try {
411
			ScheduledJobAccess jobAccess = new ScheduledJobAccess();
412
			ScheduledJobDAO scheduledJobDAO = jobAccess.getJob(jobId);
413
			
414
			jobInfoXML += 
415
				"<scheduledJobs>" + jobToXML(scheduledJobDAO) + "</scheduledJobs>";
416
			
417
		} catch (AccessException ae) {
418
			throw new ServiceException("SchedulerService.getJobInfoXML - Could not get job info for job: " 
419
					+ jobId, ae);
420
		}
421
		
422
		return jobInfoXML;
423
	}
424
	
425
	/**
426
	 * Get the information for jobs in a group in an xml format. A parameter
427
	 * key/value pair can be provided as well to limit the jobs returned.
428
	 * 
429
	 * @param groupName
430
	 *            the job group that we are searching for
431
	 * @param paramName
432
	 *            the parameter name that we are looking for. this is ignored if
433
	 *            null
434
	 * @param paramValue
435
	 *            the parameter value that we are looking for. this is ignored
436
	 *            if null
437
	 * @return an XML representation of the jobs.
438
	 */
439
	public String getJobsInfoXML(String groupName, String paramName, String paramValue) throws ServiceException {
440
		String jobInfoXML = "";
441
		
442
		try {
443
			ScheduledJobAccess jobAccess = new ScheduledJobAccess();
444
			HashMap<Long, ScheduledJobDAO> JobDAOMap = jobAccess.getJobsWithParameter(groupName, paramName, paramValue);
445
			
446
			jobInfoXML += "<scheduledWorkflowResultset>";
447
			for (Long jobDAOId : JobDAOMap.keySet()) {
448
				ScheduledJobDAO jobDAO = JobDAOMap.get(jobDAOId); 
449
				if (paramValue != null && paramName != null) {
450
					ScheduledJobParamDAO jobParamDAO = jobDAO.getJobParam(paramName);
451
					if(jobParamDAO != null && jobParamDAO.getValue().equals(paramValue)) {
452
						jobInfoXML +=  jobToXML(JobDAOMap.get(jobDAOId)); 
453
					}
454
				}
455
			}				
456
			jobInfoXML += "</scheduledWorkflowResultset>";
457
			
458
		} catch (AccessException ae) {
459
			throw new ServiceException("SchedulerService.getJobInfoXML - Could not get jobs info for group: " 
460
					+ groupName, ae);
461
		}
462
		
463
		return jobInfoXML;
464
	}
465
	
466
	/**
467
	 * Convert a single job to XML
468
	 * @param scheduledJobDAO the job we want to convert
469
	 * @return an XML representation of the job
470
	 */
471
	public String jobToXML(ScheduledJobDAO scheduledJobDAO) throws ServiceException {
472
		String jobXML = "";
473

    
474
		if (scheduledJobDAO != null) {
475
			jobXML += "<scheduledJob>";
476
			jobXML += "<id>" + scheduledJobDAO.getId() + "</id>";
477
			jobXML += "<createTime>" + scheduledJobDAO.getCreateTime() + "</createTime>";
478
			jobXML += "<modTime>" + scheduledJobDAO.getModTime() + "</modTime>";
479
			jobXML += "<status>" + scheduledJobDAO.getStatus() + "</status>";
480
			jobXML += "<name>" + scheduledJobDAO.getName() + "</name>";
481
			jobXML += "<triggerName>" + scheduledJobDAO.getName() + "</triggerName>";
482
			jobXML += "<groupName>" + scheduledJobDAO.getGroupName() + "</groupName>";
483
			jobXML += "<className>" + scheduledJobDAO.getClassName() + "</className>";
484
			String startTimeString = null;
485
			try {
486
				startTimeString = 
487
					DateUtil.getHumanReadable(scheduledJobDAO.getStartTime(), true);
488
			} catch (UtilException ue) {
489
				throw new ServiceException("SchedulerService.jobToXML - error getting human readable date for job: " 
490
						+ scheduledJobDAO.getId() + " ; " + ue.getMessage());
491
			}
492
			jobXML += "<startTime>" + startTimeString
493
					+ "</startTime>";
494
			jobXML += "<intervalValue>" + scheduledJobDAO.getIntervalValue()
495
					+ "</intervalValue>";
496
			jobXML += "<intervalUnit>" + scheduledJobDAO.getIntervalUnit()
497
					+ "</intervalUnit>";
498

    
499
			HashMap<String, ScheduledJobParamDAO> jobParams = scheduledJobDAO
500
					.getAllJobParams();
501
			for (String jobParamKey : jobParams.keySet()) {
502
				jobXML += "<jobParam name='" + jobParams.get(jobParamKey).getKey() + "'>";
503
				jobXML += "<id>" + jobParams.get(jobParamKey).getId() + "</id>";
504
				jobXML += "<createTime>" + jobParams.get(jobParamKey).getCreateTime()
505
						+ "</createTime>";
506
				jobXML += "<modTime>" + jobParams.get(jobParamKey).getModTime()
507
						+ "</modTime>";
508
				jobXML += "<status>" + jobParams.get(jobParamKey).getStatus()
509
						+ "</status>";
510
				jobXML += "<jobId>" + jobParams.get(jobParamKey).getJobId() + "</jobId>";
511
				jobXML += "<key>" + jobParams.get(jobParamKey).getKey() + "</key>";
512
				jobXML += "<value>" + jobParams.get(jobParamKey).getValue() + "</value>";
513
				jobXML += "</jobParam>";
514
			}
515
			jobXML += "</scheduledJob>";
516
		}
517

    
518
		return jobXML;
519
	}
520
	
521
	/**
522
	 * Start a job in the scheduler
523
	 * 
524
	 * @param jobName
525
	 *            the name of the job
526
	 * @param startCal
527
	 *            a calendar holding the start date of the job
528
	 * @param intervalValue
529
	 *            the run interval for the job
530
	 * @param intervalUnit
531
	 *            the unit of the run interval for the job
532
	 * @param jobClassName
533
	 *            the job class name
534
	 * @param jobGroup
535
	 *            the job group name
536
	 * @param jobParams
537
	 *            a map of additional job parameters
538
	 * @param username
539
	 *            the user name
540
	 * @param groups
541
	 *            the user's group name
542
	 */
543
	private void startJob(String jobName, Calendar startCal, Calendar endCal, int intervalValue, String intervalUnit,
544
			Class<Job> jobClass, String jobGroup, HashMap<String, String> jobParams) throws ServiceException { 
545
		
546
		JobDetail jobDetail = new JobDetail(jobName, jobGroup, jobClass);
547
		jobDetail.setJobDataMap(new JobDataMap(jobParams));
548
		
549
		char intervalChar = intervalUnit.charAt(0);
550
		
551
		// call the appropriate scheduling method depending on the schedule interval unit
552
		switch (intervalChar) {
553
		case 's':
554
		case 'S':
555
			scheduleSecondlyJob(jobName, jobClass, startCal, endCal, intervalValue, jobGroup, jobDetail);
556
			break;
557
		case 'm':
558
		case 'M':
559
			scheduleMinutelyJob(jobName, jobClass, startCal, endCal, intervalValue, jobGroup, jobDetail);
560
			break;
561
		case 'h':
562
		case 'H':
563
			scheduleHourlyJob(jobName, jobClass, startCal, endCal, intervalValue, jobGroup, jobDetail);
564
			break;
565
		case 'd':
566
		case 'D':
567
			scheduleDailyJob(jobName, jobClass, startCal, endCal, intervalValue, jobGroup, jobDetail);
568
			break;
569
		default:
570
			throw new ServiceException("SchedulerService.scheduleJob - Could not interpret interval unit: " 
571
					+ intervalUnit + ". Unit must be s, m, h or d");	
572
		}	
573
	}
574
	
575
	/**
576
	 * Schedule a job in the scheduler that has an interval based in seconds
577
	 * 
578
	 * @param jobName
579
	 *            the name of the job
580
	 * @param jobClass
581
	 *            the job class object
582
	 * @param startTime
583
	 *            the time of the first run
584
	 * @param interval
585
	 *            the interval in seconds between runs
586
	 * @param jobGroup
587
	 *            the group of this job
588
	 * @param jobDetail
589
	 *            the job detail object
590
	 */
591
	private void scheduleSecondlyJob(String jobName, Class<Job> jobClass, Calendar startTime, Calendar endTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException {
592

    
593
		Trigger trigger = TriggerUtils.makeSecondlyTrigger(interval);
594
		trigger.setName(jobName);
595
		trigger.setStartTime(startTime.getTime());
596
		if (endTime != null) {
597
			trigger.setEndTime(endTime.getTime());
598
		}
599

    
600
		try {
601
			sched.scheduleJob(jobDetail, trigger);
602
		} catch (SchedulerException se) {
603
			throw new ServiceException("SchedulerService.scheduleSecondlyJob - Could not create " 
604
					+ "scheduler: " + se.getMessage());
605
		}
606
	}
607
	
608
	/**
609
	 * Schedule a job in the scheduler that has an interval based in minutes
610
	 * 
611
	 * @param jobName
612
	 *            the name of the job
613
	 * @param jobClass
614
	 *            the job class object
615
	 * @param startTime
616
	 *            the time of the first run
617
	 * @param interval
618
	 *            the interval in minutes between runs
619
	 * @param jobGroup
620
	 *            the group of this job
621
	 * @param jobDetail
622
	 *            the job detail object
623
	 */
624
	private void scheduleMinutelyJob(String jobName, Class<Job> jobClass, Calendar startTime, Calendar endTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException {
625

    
626
		Trigger trigger = TriggerUtils.makeMinutelyTrigger(interval);
627
		trigger.setName(jobName);
628
		trigger.setStartTime(startTime.getTime());
629
		if (endTime != null) {
630
			trigger.setEndTime(endTime.getTime());
631
		}
632

    
633
		try {
634
			sched.scheduleJob(jobDetail, trigger);
635
		} catch (SchedulerException se) {
636
			throw new ServiceException("SchedulerService.scheduleMinutelyJob - Could not create " 
637
					+ "scheduler: " + se.getMessage());
638
		}
639
	}
640
	
641
	/**
642
	 * Schedule a job in the scheduler that has an interval based in hours
643
	 * 
644
	 * @param jobName
645
	 *            the name of the job
646
	 * @param jobClass
647
	 *            the job class object
648
	 * @param startTime
649
	 *            the time of the first run
650
	 * @param interval
651
	 *            the interval in hours between runs
652
	 * @param jobGroup
653
	 *            the group of this job
654
	 * @param jobDetail
655
	 *            the job detail object
656
	 */
657
	private void scheduleHourlyJob(String jobName, Class<Job> jobClass, Calendar startTime, Calendar endTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException {
658

    
659
		Trigger trigger = TriggerUtils.makeHourlyTrigger(interval);
660
		trigger.setName(jobName);
661
		trigger.setStartTime(startTime.getTime());
662
		if (endTime != null) {
663
			trigger.setEndTime(endTime.getTime());
664
		}
665

    
666
		try {
667
			sched.scheduleJob(jobDetail, trigger);
668
		} catch (SchedulerException se) {
669
			throw new ServiceException("SchedulerService.scheduleHourlyJob - Could not create " 
670
					+  "scheduler: " + se.getMessage());
671
		}
672
	}
673
	
674
	/**
675
	 * Schedule a job in the scheduler that has an interval based in days
676
	 * 
677
	 * @param jobName
678
	 *            the name of the job
679
	 * @param jobClass
680
	 *            the job class object
681
	 * @param startTime
682
	 *            the time of the first run
683
	 * @param interval
684
	 *            the interval in days between runs
685
	 * @param jobGroup
686
	 *            the group of this job
687
	 * @param jobDetail
688
	 *            the job detail object
689
	 */
690
	private void scheduleDailyJob(String jobName, Class<Job> jobClass, Calendar startTime, Calendar endTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException {
691

    
692
		Trigger trigger = TriggerUtils.makeHourlyTrigger(interval * 24);
693
		trigger.setName(jobName);
694
		trigger.setStartTime(startTime.getTime());
695
		if (endTime != null) {
696
			trigger.setEndTime(endTime.getTime());
697
		}
698

    
699
		try {
700
			sched.scheduleJob(jobDetail, trigger);
701
		} catch (SchedulerException se) {
702
			throw new ServiceException("SchedulerService.scheduleHourlyJob - Could not create " 
703
					+ "scheduler: " + se.getMessage());
704
		}
705
	}
706
	
707
	/**
708
	 * Extract the start date from the delay value
709
	 * 
710
	 * @param delay
711
	 *            a string representing the start delay in <value><unit>
712
	 *            notation where value is an integer and unit is one of s,m,h or
713
	 *            d
714
	 * @return the calendar object holding the start date
715
	 */
716
	public Calendar getStartDateFromDelay(String delay) throws ServiceException {
717
		Calendar cal = Calendar.getInstance();
718
	
719
		char delayUnit = delay.trim().charAt(delay.length() - 1);
720
		String delayStrValue = delay.trim().substring(0, delay.length() - 1);
721
		int delayValue;
722
		try {
723
			delayValue = Integer.parseInt(delayStrValue);
724
		} catch (NumberFormatException nfe) {
725
			throw new ServiceException("SchedulerService.getStartDateFromDelay - Could not " 
726
					+ "parse delay value into an integer: " + delayStrValue + " : " + nfe.getMessage());
727
		}
728
		
729
		switch (delayUnit) {
730
		case 's':
731
		case 'S':
732
			cal.add(Calendar.SECOND, delayValue);
733
			break;
734
		case 'm':
735
		case 'M':
736
			cal.add(Calendar.MINUTE, delayValue);
737
			break;
738
		case 'h':
739
		case 'H':
740
			cal.add(Calendar.HOUR, delayValue);
741
			break;
742
		case 'd':
743
		case 'D':
744
			cal.add(Calendar.DAY_OF_YEAR, delayValue);
745
			break;
746
		default:
747
			throw new ServiceException("SchedulerService.getStartDateFromDelay - Could not " 
748
					+ "interpret delay unit: " + delayUnit + ". Unit must be s, m, h or d");	
749
		}
750
		
751
		return cal;
752
	}	
753
}
(7-7/7)