Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that handles scheduling workflow jobs 
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.workflow;
28

    
29
import java.io.IOException;
30
import java.util.Calendar;
31
import java.util.Hashtable;
32
import java.util.HashMap;
33

    
34
import javax.servlet.http.HttpServletRequest;
35
import javax.servlet.http.HttpServletResponse;
36
import javax.servlet.ServletException;
37

    
38
import org.apache.log4j.Logger;
39

    
40
import edu.ucsb.nceas.metacat.MetaCatServlet;
41
import edu.ucsb.nceas.metacat.scheduler.BaseScheduler;
42
import edu.ucsb.nceas.metacat.scheduler.ScheduledJobAccess;
43
import edu.ucsb.nceas.metacat.scheduler.ScheduledJobDAO;
44
import edu.ucsb.nceas.metacat.scheduler.ScheduledJobParamDAO;
45
import edu.ucsb.nceas.metacat.scheduler.SchedulerService;
46
import edu.ucsb.nceas.metacat.scheduler.MetacatSchedulerException;
47
import edu.ucsb.nceas.metacat.shared.AccessException;
48
import edu.ucsb.nceas.metacat.shared.ServiceException;
49
import edu.ucsb.nceas.metacat.util.ErrorSendingErrorException;
50
import edu.ucsb.nceas.metacat.util.ResponseUtil;
51
import edu.ucsb.nceas.metacat.util.RequestUtil;
52
import edu.ucsb.nceas.utilities.DateUtil;
53
import edu.ucsb.nceas.utilities.UtilException;
54

    
55
/**
56
 * @author daigle
57
 *
58
 */
59
/**
60
 * @author daigle
61
 *
62
 */
63
public class WorkflowScheduler extends BaseScheduler {
64
	
65
	private static WorkflowScheduler workflowScheduler = null;
66
	
67
	private static Logger logMetacat = Logger.getLogger(WorkflowScheduler.class);
68
	
69
	private static String WORKFLOW_JOB_GROUP = "workflow";
70
	private static String WORKFLOW_JOB_CLASS = "edu.ucsb.nceas.metacat.workflow.WorkflowJob";
71

    
72
	/**
73
	 * private constructor since this is a singleton
74
	 */
75
	private WorkflowScheduler()  {}
76
	
77
	/**
78
	 * Get the single instance of SchedulerService.
79
	 * 
80
	 * @return the single instance of SchedulerService
81
	 */
82
	public static WorkflowScheduler getInstance() {
83
		if (workflowScheduler == null) {
84
			workflowScheduler = new WorkflowScheduler();
85
		}
86
		return workflowScheduler;
87
	}
88
	
89
	/**
90
	 * Scheduling a workflow
91
	 * 
92
	 * @param request
93
	 *            the servlet request object
94
	 * @param response
95
	 *            the servlet response object
96
	 * @param params
97
	 *            the request parameters
98
	 * @param username
99
	 *            the user
100
	 * @param groups
101
	 *            the user's group
102
	 */
103
	public void scheduleJob(HttpServletRequest request, HttpServletResponse response, 
104
			Hashtable<String, String[]> params, String username,
105
			String[] groups) throws MetacatSchedulerException {
106
		 		
107
		String delays[] = params.get("delay");
108
		String startTimes[] = params.get("starttime");
109
		String endTimes[] = params.get("endtime");
110
		HashMap<String, String> jobParams = new HashMap<String, String>();
111
		Calendar startCal = null;
112
		Calendar endCal = null;
113

    
114
		try {
115
			SchedulerService schedulerService = SchedulerService.getInstance();
116

    
117
			// get start time or delay.  Start time takes precedence if both exist.
118
			if (startTimes != null && startTimes.length > 0) {
119
				startCal = DateUtil.humanReadableToCalendar(startTimes[0], "MM/dd/yyyy HH:mm:ss");
120
			} else if (delays != null && delays.length > 0) {
121
				startCal = schedulerService.getStartDateFromDelay(delays[0]);
122
			} else {
123
				// if delay and starttime were not provided, set date to now.
124
				startCal = Calendar.getInstance();
125
			}
126
			
127
			// get end time.  null is fine.
128
			if (endTimes != null && endTimes.length > 0) {
129
				endCal = DateUtil.humanReadableToCalendar(endTimes[0], "MM/dd/yyyy HH:mm:ss");
130
			} 
131

    
132
			// interval value must exist
133
			String intervalValues[] = params.get("intervalvalue");
134
			if (intervalValues == null || intervalValues.length == 0) {
135
				throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - intervalvalue field must be populated "
136
								+ "in scheduler parameters when scheduling job.");
137
			}
138
			String intervalStrValue = intervalValues[0];
139
			int intervalValue = Integer.parseInt(intervalStrValue);
140
			
141
			// interval unit must exist
142
			String intervalUnits[] = params.get("intervalunit");
143
			if (intervalUnits == null || intervalUnits.length == 0) {
144
				throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - intervalunit field must be populated "
145
								+ "in scheduler parameters when scheduling job.");
146
			}
147
			String intervalUnit = intervalUnits[0];
148

    
149
			// workflow id must exist.  Add to job params
150
			String workflowids[] = params.get("workflowid");
151
			if (workflowids == null || workflowids.length == 0) {
152
				throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - workflowid field must be populated "
153
								+ "in scheduler parameters when scheduling job.");
154
			}
155
			jobParams.put("workflowid", workflowids[0]);
156
			
157
			// kar id must exist.  Add to job params
158
			String karids[] = params.get("karid");
159
			if (karids == null || karids.length == 0) {
160
				throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - karid field must be populated "
161
								+ "in scheduler parameters when scheduling job.");
162
			}
163
			jobParams.put("karid", karids[0]);
164
			
165
			
166
			// workflow name unit must exist.  Add to job params
167
			String workflownames[] = params.get("workflowname");
168
			if (workflownames == null || workflownames.length == 0) {
169
				throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - workflowname field must be populated "
170
								+ "in scheduler parameters when scheduling job.");
171
			}
172
			jobParams.put("workflowname", workflownames[0]);
173

    
174
			String jobName = WORKFLOW_JOB_GROUP
175
					+ Calendar.getInstance().getTimeInMillis();
176

    
177
			// Schedule the job
178
			String xmlResult = schedulerService.scheduleJob(jobName, startCal, endCal, intervalValue, intervalUnit,
179
					WORKFLOW_JOB_CLASS, WORKFLOW_JOB_GROUP, jobParams, username, groups);
180

    
181
			// if there is a forwardto param on the request, then send the user to the page
182
			// referenced in that param, otherwise, just send the xml back.
183
			String forwardtos[] = params.get("forwardto");
184
			String forwardto = null;
185
			if (forwardtos != null && forwardtos.length > 0) {
186
				forwardto = forwardtos[0];
187
			}
188
			
189
			if (forwardto != null) {
190
				String qformats[] = params.get("qformat");
191
				String qformat = null;
192
				if (qformats != null && qformats.length > 0) {
193
					qformat = qformats[0];
194
				}
195
				
196
				String destination = "/style/skins/" + qformat + "/" + forwardto
197
					+ "?workflowid=" + jobParams.get("workflowid") 
198
					+ "&karid=" + jobParams.get("karid");			
199
				RequestUtil.forwardRequest(request, response, destination);
200
			} else {
201
				ResponseUtil.sendSuccessXML(response, xmlResult);
202
			}
203
			
204
		} catch (UtilException ue) {
205
			throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - Utility issue when scheduling job: " + ue.getMessage());
206
		} catch (ServiceException se) {
207
			throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - Service issue when scheduling job", se);
208
		} catch (IOException ioe) {
209
			throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - I/O issue when scheduling job: " + ioe.getMessage());
210
		} catch (ServletException se) {
211
			throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - Servlet issue when scheduling job: " + se.getMessage());
212
		} catch (ErrorSendingErrorException esee) {
213
			throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - Issue sending error when scheduling job: " + esee.getMessage());			
214
		}
215
	}
216
	
217
	/**
218
	 * Unschedule a job
219
	 * 
220
	 * @param request
221
	 *            the servlet request object
222
	 * @param response
223
	 *            the servlet response object
224
	 * @param params
225
	 *            the request parameters
226
	 * @param username
227
	 *            the user
228
	 * @param groups
229
	 *            the user's group
230
	 */
231
	public void unScheduleJob(HttpServletRequest request, HttpServletResponse response,
232
			Hashtable<String, String[]> params, String username, String[] groups)
233
			throws MetacatSchedulerException {
234
		try {
235
			// workflow job id must exist
236
			String jobNames[] = params.get("workflowjobid");
237
			if (jobNames == null || jobNames.length == 0) {
238
				throw new MetacatSchedulerException("SchedulerService.unScheduleJob - workflowjobid " 
239
						+ "field must be populated in scheduler parameters when unscheduling job.");
240
			}
241
			String jobName = jobNames[0];
242

    
243
			// unschedule the job
244
			SchedulerService schedulerService = SchedulerService.getInstance();
245
			String xmlResult = schedulerService.unScheduleJob(jobName, username, groups);
246
			
247
			
248
			String forwardtos[] = params.get("forwardto");
249
			String forwardto = null;
250
			if (forwardtos != null && forwardtos.length > 0) {
251
				forwardto = forwardtos[0];
252
			}
253
			
254
			// if there is a forwardto param on the request, then send the user to the page
255
			// referenced in that param, otherwise, just send the xml back.
256
			if (forwardto != null) {
257
				String qformats[] = params.get("qformat");
258
				String qformat = null;
259
				if (qformats != null && qformats.length > 0) {
260
					qformat = qformats[0];
261
				}
262
				
263
				ScheduledJobAccess jobAccess = new ScheduledJobAccess();
264
				ScheduledJobDAO jobDAO = jobAccess.getJobByName(jobName);
265
				
266
				// we need to include the workflow id in the forward url
267
				ScheduledJobParamDAO workflowIdJobParamDAO = jobDAO.getJobParam("workflowid");
268
				if (workflowIdJobParamDAO == null) {
269
					throw new MetacatSchedulerException("WorkflowScheduler.unScheduleJob - could not find workflow " 
270
							+ "id when unscheduling job: " + jobName);
271
				}	
272
				
273
				// we need to include the workflow id in the forward url
274
				ScheduledJobParamDAO karJobParamDAO = jobDAO.getJobParam("karid");
275
				if (karJobParamDAO == null) {
276
					throw new MetacatSchedulerException("WorkflowScheduler.unScheduleJob - could not find kar " 
277
							+ "id when unscheduling job: " + jobName);
278
				}
279
				
280
				// we need to include the workflow id in the url
281
				ScheduledJobParamDAO workflowNameJobParamDAO = jobDAO.getJobParam("workflowname");
282
				if (workflowNameJobParamDAO == null) {
283
					throw new MetacatSchedulerException("WorkflowScheduler.unScheduleJob - could not find workflow " 
284
							+ "name when unscheduling job: " + jobName);
285
				}
286
				
287
				String destination = "/style/skins/" + qformat + "/" + forwardto
288
					+ "?workflowid=" + workflowIdJobParamDAO.getValue() 
289
					+ "&karid=" + karJobParamDAO.getValue()
290
					+ "&workflowname=" + workflowNameJobParamDAO.getValue();
291
				
292
				RequestUtil.forwardRequest(request, response, destination.toString());
293
			} else {
294
				ResponseUtil.sendSuccessXML(response, xmlResult);
295
			}
296
			ResponseUtil.sendSuccessXML(response, xmlResult);
297
		} catch (ServiceException se) {
298
			throw new MetacatSchedulerException(
299
					"WorkflowScheduler.unScheduleJob - Service issue unscheduling job",
300
					se);
301
		} catch (Exception e) {
302
			throw new MetacatSchedulerException(
303
					"WorkflowScheduler.unScheduleJob - Generic issue unscheduling job: "
304
							+ e.getMessage());
305
		}
306
	}
307
	
308
	/**
309
	 * reschedule job
310
	 * 
311
	 * @param request
312
	 *            the servlet request object
313
	 * @param response
314
	 *            the servlet response object
315
	 * @param params
316
	 *            the request parameters
317
	 * @param username
318
	 *            the user
319
	 * @param groups
320
	 *            the user's group
321
	 */
322
	public void reScheduleJob(HttpServletRequest request, HttpServletResponse response, 
323
			Hashtable<String, String[]> params, String username,
324
			String[] groups) throws MetacatSchedulerException {
325
		 		
326
		try {
327
			// workflow job id must exist
328
			String jobNames[] = params.get("workflowjobid");	
329
			if (jobNames == null || jobNames.length == 0) {
330
				throw new MetacatSchedulerException("WorkflowScheduler.reScheduleJob - workflowjobid field must be populated "
331
						+ "in scheduler parameters when rescheduling job.");
332
			}			
333
			String jobName = jobNames[0];
334
	
335
			ScheduledJobAccess jobAccess = new ScheduledJobAccess();
336
			ScheduledJobDAO jobDAO = jobAccess.getJobByName(jobName);
337
			
338
			// reschedule the job
339
			SchedulerService schedulerService = SchedulerService.getInstance();
340
			String result = schedulerService.rescheduleJob(jobDAO, username, groups);
341

    
342
			// if there is a forwardto param on the request, then send the user to the page
343
			// referenced in that param, otherwise, just send the xml back.
344
			String forwardtos[] = params.get("forwardto");
345
			String forwardto = null;
346
			if (forwardtos != null && forwardtos.length > 0) {
347
				forwardto = forwardtos[0];
348
			}
349
			
350
			if (forwardto != null) {
351
				String qformats[] = params.get("qformat");
352
				String qformat = null;
353
				if (qformats != null && qformats.length > 0) {
354
					qformat = qformats[0];
355
				}
356
				
357
				// we need to include the workflow id in the url
358
				ScheduledJobParamDAO workflowIdJobParamDAO = jobDAO.getAllJobParams().get("workflowid");
359
				if (workflowIdJobParamDAO == null) {
360
					throw new MetacatSchedulerException("WorkflowScheduler.reScheduleJob - could not find workflow " 
361
							+ "id when deleting job: " + jobName);
362
					
363
				}
364
				
365
				// we need to include the workflow id in the url
366
				ScheduledJobParamDAO karJobParamDAO = jobDAO.getJobParam("karid");
367
				if (karJobParamDAO == null) {
368
					throw new MetacatSchedulerException("WorkflowScheduler.reScheduleJob - could not find kar " 
369
							+ "id when deleting job: " + jobName);
370
				}
371
				
372
				// we need to include the workflow id in the url
373
				ScheduledJobParamDAO workflowNameJobParamDAO = jobDAO.getJobParam("workflowname");
374
				if (workflowNameJobParamDAO == null) {
375
					throw new MetacatSchedulerException("WorkflowScheduler.reScheduleJob - could not find workflow " 
376
							+ "name when deleting job: " + jobName);
377
				}
378
				
379
				String destination = "/style/skins/" + qformat + "/" + forwardto
380
					+ "?workflowid=" + workflowIdJobParamDAO.getValue()	
381
					+ "&karid=" + karJobParamDAO.getValue()
382
					+ "&workflowname=" + workflowNameJobParamDAO.getValue();
383
				
384
				RequestUtil.forwardRequest(request, response, destination);
385
			} else {
386
				ResponseUtil.sendSuccessXML(response, result);
387
			}
388
			
389
		} catch (AccessException ae) {
390
			throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - DB access issue when scheduling job  : ", ae);
391
		} catch (ServiceException se) {
392
			throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - Service issue scheduling job", se);
393
		} catch (IOException ioe) {
394
			throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - I/O issue scheduling job: " + ioe.getMessage());
395
		} catch (ServletException se) {
396
			throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - Servlet issue scheduling job: " + se.getMessage());
397
		} catch (ErrorSendingErrorException esee) {
398
			throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - Issue sending erro when scheduling job: " + esee.getMessage());			
399
		}
400
	}
401
	
402
	/**
403
	 * delete job - to be implemented
404
	 */
405
	public void deleteJob(HttpServletRequest request, HttpServletResponse response, 
406
			Hashtable<String, String[]> params, String username, String[] groups) throws MetacatSchedulerException {
407
		 try {
408
		// workflow job id must exist
409
		String jobNames[] = params.get("workflowjobid");	
410
		if (jobNames == null || jobNames.length == 0) {
411
			throw new MetacatSchedulerException("WorkflowScheduler.deleteJob - workflowjobid field must be populated "
412
					+ "in scheduler parameters when deleting job.");
413
		}			
414
		String jobName = jobNames[0];
415

    
416
		ScheduledJobAccess jobAccess = new ScheduledJobAccess();
417
		ScheduledJobDAO jobDAO = jobAccess.getJobByName(jobName);
418
		
419
		// delete the job
420
		SchedulerService schedulerService = SchedulerService.getInstance();
421
		String result = schedulerService.deleteJob(jobDAO, username, groups);
422
		
423
		// if there is a forwardto param on the request, then send the user to the page
424
		// referenced in that param, otherwise, just send the xml back.
425
		String forwardtos[] = params.get("forwardto");
426
		String forwardto = null;
427
		if (forwardtos != null && forwardtos.length > 0) {
428
			forwardto = forwardtos[0];
429
		}
430
		
431
		if (forwardto != null) {
432
			String qformats[] = params.get("qformat");
433
			String qformat = null;
434
			if (qformats != null && qformats.length > 0) {
435
				qformat = qformats[0];
436
			}
437
			
438
			// we need to include the workflow id in the url
439
			ScheduledJobParamDAO workflowIdJobParamDAO = jobDAO.getAllJobParams().get("workflowid");
440
			if (workflowIdJobParamDAO == null) {
441
				throw new MetacatSchedulerException("WorkflowScheduler.deleteJob - could not find workflow " 
442
						+ "id when deleting job: " + jobName);
443
				
444
			}
445
			
446
			// we need to include the workflow id in the url
447
			ScheduledJobParamDAO karJobParamDAO = jobDAO.getJobParam("karid");
448
			if (karJobParamDAO == null) {
449
				throw new MetacatSchedulerException("WorkflowScheduler.deleteJob - could not find kar " 
450
						+ "id when deleting job: " + jobName);
451
			}
452
			
453
			// we need to include the workflow id in the url
454
			ScheduledJobParamDAO workflowNameJobParamDAO = jobDAO.getJobParam("workflowname");
455
			if (workflowNameJobParamDAO == null) {
456
				throw new MetacatSchedulerException("WorkflowScheduler.deleteJob - could not find workflow " 
457
						+ "name when deleting job: " + jobName);
458
			}
459
			
460
			String destination = "/style/skins/" + qformat + "/" + forwardto
461
				+ "?workflowid=" + workflowIdJobParamDAO.getValue()	
462
				+ "&karid=" + karJobParamDAO.getValue()
463
				+ "&workflowname=" + workflowNameJobParamDAO.getValue();
464
			
465
			RequestUtil.forwardRequest(request, response, destination);
466
		} else {
467
			ResponseUtil.sendSuccessXML(response, result);
468
		}
469
		
470
		} catch (AccessException ae) {
471
				throw new MetacatSchedulerException("WorkflowScheduler.deleteJob - DB access issue when deleting job  : ", ae);
472
		} catch (ServiceException se) {
473
			throw new MetacatSchedulerException("WorkflowScheduler.deleteJob - Service issue deleting job", se);
474
		} catch (IOException ioe) {
475
			throw new MetacatSchedulerException("WorkflowScheduler.deleteJob - I/O issue deleting job: " + ioe.getMessage());
476
		} catch (ServletException se) {
477
			throw new MetacatSchedulerException("WorkflowScheduler.deleteJob - Servlet issue deleting job: " + se.getMessage());
478
		} catch (ErrorSendingErrorException esee) {
479
			throw new MetacatSchedulerException("WorkflowScheduler.deleteJob - Issue sending erro when deleting job: " + esee.getMessage());			
480
		}
481
	}
482
	
483
	/**
484
	 * get job information for a given workflow in xml format
485
	 * 
486
	 * @param request
487
	 *            the servlet request object
488
	 * @param response
489
	 *            the servlet response object
490
	 * @param params
491
	 *            the request parameters
492
	 * @param username
493
	 *            the user
494
	 * @param groups
495
	 *            the user's group
496
	 */
497
	public void getJobs(HttpServletRequest request, HttpServletResponse response, 
498
			Hashtable<String, String[]> params, String username, String[] groups) throws MetacatSchedulerException {
499
		
500
		String workFlowId = null;
501
		String qformat = "";
502
		
503
		String workFlowIds[] = params.get("workflowid");
504
		if (workFlowIds != null && workFlowIds.length != 0) {
505
			workFlowId = workFlowIds[0];
506
		}
507
		
508
        if (params.containsKey("qformat")) {
509
            qformat = params.get("qformat")[0];
510
        }
511
		
512
		try {
513
			// get the job info in xml format
514
			String xmlResult = SchedulerService.getInstance().getJobsInfoXML(WORKFLOW_JOB_GROUP, "workflowid", workFlowId);
515
			logMetacat.debug("WorkflowScheduler.getJobs - xmlResult: " + xmlResult);
516
			
517
			if (qformat == null || qformat.equals(MetaCatServlet.XMLFORMAT)) {
518
				ResponseUtil.send(response, xmlResult);
519
			} else {				
520
				ResponseUtil.transformAndSendXML(response, xmlResult, "-//NCEAS//scheduledWorkflowResultset//EN", 
521
					"-//W3C//HTML//EN", qformat, params);
522
			}
523
		} catch (ServiceException se) {
524
			throw new MetacatSchedulerException("WorkflowScheduler.getJobs - Service issue getting jobs", se);
525
		} catch (Exception e) {
526
			throw new MetacatSchedulerException("WorkflowScheduler.getJobs - Generic issue getting jobs: " 
527
					+ e.getMessage());
528
		}		
529
	}	
530
}
(2-2/2)