Revision 4971
Added by daigle over 15 years ago
lib/style/skins/sanparks/sanparks-scheduled-jobs.css | ||
---|---|---|
156 | 156 |
width: 100px; |
157 | 157 |
} |
158 | 158 |
|
159 |
.result-header { |
|
160 |
margin-bottom: 5px; |
|
161 |
} |
|
162 |
|
|
159 | 163 |
.result-header-emphasis { |
160 | 164 |
font-size: 16px; |
161 | 165 |
margin-bottom: 5px; |
lib/style/skins/sanparks/sanparks-tpc.css | ||
---|---|---|
132 | 132 |
font-size: 16px; |
133 | 133 |
} |
134 | 134 |
|
135 |
.result-header { |
|
136 |
float: none; |
|
137 |
} |
|
138 |
|
|
135 | 139 |
/********************************************************************** |
136 | 140 |
* tpc search result specific settings |
137 | 141 |
**********************************************************************/ |
138 | 142 |
|
139 | 143 |
.col1 { |
140 |
width: 280px;
|
|
144 |
width: 250px;
|
|
141 | 145 |
text-align: left; |
142 | 146 |
font-weight: bold; |
143 | 147 |
} |
144 | 148 |
|
145 | 149 |
.col2 { |
146 |
width: 147px;
|
|
150 |
width: 130px;
|
|
147 | 151 |
} |
148 | 152 |
|
149 | 153 |
.col3 { |
150 |
width: 110px;
|
|
154 |
width: 100px;
|
|
151 | 155 |
} |
152 | 156 |
|
153 | 157 |
.col4 { |
154 |
width: 148px;
|
|
158 |
width: 190px;
|
|
155 | 159 |
border-right: none; |
156 | 160 |
} |
lib/style/common/searchWorkflowSection.jsp | ||
---|---|---|
36 | 36 |
<script language="JavaScript" type="text/JavaScript" src="<%=STYLE_COMMON_URL%>/ajax-utils.js"></script> |
37 | 37 |
<script language="JavaScript" type="text/JavaScript" src="<%=STYLE_COMMON_URL%>/searchWorkflow.js"></script> |
38 | 38 |
</head> |
39 |
<body onload="setWorkflowQueryFormField('tpcSearch');getResultsSection('<%=SERVLET_URL%>','tpcSearch','workflow-search-results')">
|
|
39 |
<body onload="setWorkflowQueryFormField('tpcSearch');submitFormIntoDiv('<%=SERVLET_URL%>','tpcSearch','workflow-search-results')">
|
|
40 | 40 |
<div class=content-section> |
41 | 41 |
<div class="content-subsection search-section" id="search-section"> |
42 | 42 |
<form name="tpcSearch" id="tpcSearch"> |
... | ... | |
56 | 56 |
<option values="workflow-id" onclick="addSearchDropdownBefore('tpcSearch','Workflow-id','workflow-id','co|eq|sw|ew','form-base-row')">Workflow ID</option> |
57 | 57 |
</select> |
58 | 58 |
|
59 |
<input class="submit-button" value="Search" type="button" onclick="setWorkflowQueryFormField('tpcSearch');getResultsSection('<%=SERVLET_URL%>','tpcSearch','workflow-search-results')">
|
|
59 |
<input class="submit-button" value="Search" type="button" onclick="setWorkflowQueryFormField('tpcSearch');submitFormIntoDiv('<%=SERVLET_URL%>','tpcSearch','workflow-search-results')">
|
|
60 | 60 |
</div> |
61 | 61 |
</form> |
62 | 62 |
</div> |
lib/style/common/scheduleWorkflow.js | ||
---|---|---|
1 |
/* |
|
2 |
*/ |
|
3 |
|
|
1 |
/* |
|
2 |
* '$RCSfile$' |
|
3 |
* Purpose: Basic funtions to support showing the schedule workflows |
|
4 |
* pages |
|
5 |
* Copyright: 2009 Regents of the University of California and the |
|
6 |
* National Center for Ecological Analysis and Synthesis |
|
7 |
* Authors: Michael Daigle |
|
8 |
* |
|
9 |
* '$Author: leinfelder $' |
|
10 |
* '$Date: 2008-06-17 13:16:32 -0700 (Tue, 17 Jun 2008) $' |
|
11 |
* '$Revision: 4006 $' |
|
12 |
* |
|
13 |
* This program is free software; you can redistribute it and/or modify |
|
14 |
* it under the terms of the GNU General Public License as published by |
|
15 |
* the Free Software Foundation; either version 2 of the License, or |
|
16 |
* (at your option) any later version. |
|
17 |
* |
|
18 |
* This program is distributed in the hope that it will be useful, |
|
19 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
20 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
21 |
* GNU General Public License for more details. |
|
22 |
* |
|
23 |
* You should have received a copy of the GNU General Public License |
|
24 |
* along with this program; if not, write to the Free Software |
|
25 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
26 |
*/ |
|
27 |
|
|
28 |
/* puts together the url to get the workflow section of a page given the workflow |
|
29 |
* id. |
|
30 |
* Params: |
|
31 |
* url - metacat url to hit |
|
32 |
* workflowId - get all runs for this id |
|
33 |
* workflowName - used for display purposes. |
|
34 |
* divId - the name of the div where the results should be put |
|
35 |
*/ |
|
4 | 36 |
function getWorkflowRunSection(url, workflowId, workflowName, divId) { |
5 | 37 |
var requestUrl = url + '?action=getScheduledWorkflow&workflowid=' + workflowId + '&qformat=sanparks&workflowname=' + workflowName; |
6 | 38 |
var submitResults = submitUrlIntoDiv(requestUrl, divId); |
7 | 39 |
} |
8 | 40 |
|
9 |
function showSchedulePage(workflowId, schedulePage, qformat) { |
|
10 |
url = document.URL + '/../' + workflowRunPage + '?workflowid=' + workflowId + '?qformat=' + qformat; |
|
11 |
//alert('new url: ' + url); |
|
12 |
window.location = url; |
|
13 |
} |
|
14 |
|
|
15 |
function scheduleWorkflowRun(url, workflowId, startTime, interval, karId) { |
|
16 |
requestUrl = |
|
17 |
url + '?action=scheduleWorkflow&starttime=' + startTime |
|
18 |
+ '&interval=' + interval + '&jobparam_karId=' + karId; |
|
19 |
//alert('new url: ' + url); |
|
20 |
window.location = url; |
|
21 |
} |
|
22 |
|
|
23 | 41 |
|
lib/style/common/searchWorkflowRunSection.jsp | ||
---|---|---|
37 | 37 |
<script language="JavaScript" type="text/JavaScript" src="<%=STYLE_COMMON_URL%>/searchWorkflowRun.js"></script> |
38 | 38 |
|
39 | 39 |
</head> |
40 |
<body onload="setWorkflowQueryFormField('tpcSearch');getResultsSection('<%=SERVLET_URL%>','tpcSearch','workflow-search-results')">
|
|
40 |
<body onload="setWorkflowQueryFormField('tpcSearch');submitFormIntoDiv('<%=SERVLET_URL%>','tpcSearch','workflow-search-results')">
|
|
41 | 41 |
<div class=content-section> |
42 | 42 |
<div class="content-subsection search-section" id="search-section"> |
43 | 43 |
<form name="tpcSearch" id="tpcSearch"> |
... | ... | |
67 | 67 |
<option values="status" onclick="addSearchDropdownBefore('tpcSearch','Status','Status','is|in','form-base-row')">Status</option> |
68 | 68 |
</select> |
69 | 69 |
|
70 |
<input class="submit-button" value="Search" type="button" onclick="setWorkflowQueryFormField('tpcSearch');getResultsSection('<%=SERVLET_URL%>','tpcSearch','workflow-search-results')">
|
|
70 |
<input class="submit-button" value="Search" type="button" onclick="setWorkflowQueryFormField('tpcSearch');submitFormIntoDiv('<%=SERVLET_URL%>','tpcSearch','workflow-search-results')">
|
|
71 | 71 |
</div> |
72 | 72 |
</form> |
73 | 73 |
</div> |
lib/style/common/searchWorkflow.js | ||
---|---|---|
1 |
/* |
|
2 |
* '$RCSfile$' |
|
3 |
* Purpose: Basic funtions to support searching workflows |
|
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: leinfelder $' |
|
9 |
* '$Date: 2008-06-17 13:16:32 -0700 (Tue, 17 Jun 2008) $' |
|
10 |
* '$Revision: 4006 $' |
|
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 |
|
|
1 | 27 |
/* |
2 | 28 |
* Generate a workflow query string. this assumes that search fields meet the |
3 | 29 |
* following criteria in the web page: |
4 |
* -- search input fields have an ID that starts with sf_ |
|
5 |
* -- the search input field name is the xpath of the value to search |
|
30 |
* -- search input fields have an ID that starts with sf- |
|
6 | 31 |
* -- if there is a search mode dropdown for an input field in the form, it's ID |
7 |
* should use the same convention as the input field, but start with sm_ |
|
8 |
* (i.e. the search mode input for the sf_firstname input would be sm_firstname) |
|
9 |
* -- the value |
|
32 |
* should use the same convention as the input field, but start with sm- |
|
33 |
* (i.e. the search mode input for the sf-firstname input would be sm-firstname) |
|
10 | 34 |
*/ |
11 |
|
|
12 | 35 |
function setWorkflowQueryFormField(formId) { |
13 | 36 |
var queryString = ""; |
14 | 37 |
queryString += "<pathquery version='1.2'>"; |
... | ... | |
46 | 69 |
queryField.value = queryString; |
47 | 70 |
} |
48 | 71 |
|
72 |
/* |
|
73 |
* Generate individual query terms for all the search input fields in a search |
|
74 |
* form. There must be a case for each search field handle explicitly below. |
|
75 |
* This assumes: |
|
76 |
* -- search input fields have an ID that starts with sf- |
|
77 |
* -- if there is a search mode dropdown for an input field in the form, it's ID |
|
78 |
* should use the same convention as the input field, but start with sm- |
|
79 |
* (i.e. the search mode input for the sf-firstname input would be sm-firstname) |
|
80 |
*/ |
|
49 | 81 |
function getQueryTerm(sfElement) { |
50 | 82 |
var baseId = sfElement.id.substring(3, sfElement.id.length); |
51 | 83 |
var searchMode = "contains"; |
... | ... | |
115 | 147 |
return pathExpr; |
116 | 148 |
} |
117 | 149 |
|
118 |
function getResultsSection(url, formId, divId) { |
|
119 |
var submitResults = submitFormIntoDiv(url, formId, divId); |
|
120 |
} |
|
121 |
|
|
122 |
function showWorkflowRuns(workflowId, workflowRunPage) { |
|
123 |
url = document.URL + '/../' + workflowRunPage + '?workflowid=' + workflowId; |
|
124 |
//alert('new url: ' + url); |
|
125 |
window.location = url; |
|
126 |
} |
|
127 |
|
|
128 | 150 |
|
lib/style/common/scheduledWorkflowResultset.xsl | ||
---|---|---|
1 | 1 |
<?xml version="1.0"?> |
2 | 2 |
<!-- |
3 | 3 |
* '$RCSfile$' |
4 |
* Authors: Matt Jones, CHad Berkley
|
|
4 |
* Authors: Michael Daigle
|
|
5 | 5 |
* Copyright: 2009 Regents of the University of California and the |
6 | 6 |
* National Center for Ecological Analysis and Synthesis |
7 | 7 |
* For Details: http://www.nceas.ucsb.edu/ |
lib/style/common/searchWorkflowResultset.xsl | ||
---|---|---|
40 | 40 |
|
41 | 41 |
<div class="result-header-section"> |
42 | 42 |
<div class="result-header">TPC Workflows</div> |
43 |
<div class="result-header-emphasis">(<xsl:number value="count(resultset/document)" /> |
|
44 |
<xsl:if test="count(resultset/document) != 1"> items</xsl:if> |
|
45 |
<xsl:if test="count(resultset/document) = 1"> item</xsl:if> |
|
46 |
found) |
|
47 |
</div> |
|
48 | 43 |
</div> |
49 | 44 |
<div class="row row-header" > |
50 | 45 |
<div class="col col1">TPC Name</div> |
... | ... | |
86 | 81 |
<xsl:attribute name="href">./scheduleWorkflowRun.jsp?workflowid=<xsl:value-of select='./param[@name="/entity/property[@name='entityId']/@value"]' />&karid=<xsl:value-of select='./param[@name="/entity/property[@name='karLSID']/@value"]' />&workflowname=<xsl:value-of select='./param[@name="/entity/@name"]' /></xsl:attribute> |
87 | 82 |
Schedule |
88 | 83 |
</a> |
84 |
<span> | </span> |
|
85 |
<a> |
|
86 |
<xsl:attribute name="class">underlined</xsl:attribute> |
|
87 |
<xsl:attribute name="href"> |
|
88 |
<xsl:value-of select='$contextURL' />/metacat?action=read&docid=<xsl:value-of select='./param[@name="/entity/property[@name='karLSID']/@value"]' /> |
|
89 |
</xsl:attribute> |
|
90 |
Download |
|
91 |
</a> |
|
89 | 92 |
</div> |
90 | 93 |
</div> |
91 | 94 |
</xsl:if> |
lib/style/common/ajax-utils.js | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* '$RCSfile$' |
3 |
* Purpose: Default style sheet for KNP project web pages |
|
4 |
* Using this stylesheet rather than placing styles directly in |
|
5 |
* the KNP web documents allows us to globally change the |
|
6 |
* formatting styles of the entire site in one easy place. |
|
3 |
* Purpose: Basic Ajax utilities |
|
7 | 4 |
* Copyright: 2009 Regents of the University of California and the |
8 | 5 |
* National Center for Ecological Analysis and Synthesis |
9 |
* Authors: Matt Jones
|
|
6 |
* Authors: Michael Daigle
|
|
10 | 7 |
* |
11 | 8 |
* '$Author: daigle $' |
12 | 9 |
* '$Date: 2008-07-06 21:25:34 -0700 (Sun, 06 Jul 2008) $' |
... | ... | |
27 | 24 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
28 | 25 |
*/ |
29 | 26 |
|
27 |
/* submits a form via ajax and inserts the results into the given div |
|
28 |
* Params: |
|
29 |
* url - url to hit |
|
30 |
* formId - id of the form to submit |
|
31 |
* divId - the name of the div where the results should be put |
|
32 |
*/ |
|
30 | 33 |
function submitFormIntoDiv(url, formId, divId) { |
31 | 34 |
//alert('Sending form: ' + formId + " to url: " + url); |
32 | 35 |
var formObj = document.getElementById(formId); |
... | ... | |
37 | 40 |
}); |
38 | 41 |
} |
39 | 42 |
|
43 |
/* submits a url via ajax and inserts the results into the given div |
|
44 |
* Params: |
|
45 |
* url - url to hit |
|
46 |
* divId - the name of the div where the results should be put |
|
47 |
*/ |
|
40 | 48 |
function submitUrlIntoDiv(url, divId) { |
41 | 49 |
//alert('Sending url: ' + url); |
42 | 50 |
|
lib/style/common/scheduleWorkflowRunSection.jsp | ||
---|---|---|
70 | 70 |
<% |
71 | 71 |
if (request.getParameter("workflowid") != null) { |
72 | 72 |
%> |
73 |
<input name='jobparam_workflowid' value='<%=request.getParameter("workflowid")%>' type='hidden' />
|
|
73 |
<input name='workflowid' value='<%=request.getParameter("workflowid")%>' type='hidden' /> |
|
74 | 74 |
<% |
75 | 75 |
} |
76 | 76 |
if (request.getParameter("karid") != null) { |
77 | 77 |
%> |
78 |
<input name='jobparam_karid' value='<%=request.getParameter("karid")%>' type='hidden' />
|
|
78 |
<input name='karid' value='<%=request.getParameter("karid")%>' type='hidden' /> |
|
79 | 79 |
<% |
80 | 80 |
} |
81 | 81 |
if (request.getParameter("workflowname") != null) { |
82 | 82 |
%> |
83 |
<input name='jobparam_workflowname' value='<%=request.getParameter("workflowname")%>' type='hidden' />
|
|
83 |
<input name='workflowname' value='<%=request.getParameter("workflowname")%>' type='hidden' /> |
|
84 | 84 |
<% |
85 | 85 |
} |
86 | 86 |
%> |
lib/style/common/searchWorkflowRun.js | ||
---|---|---|
18 | 18 |
queryString += "<returnfield>/property[@name=\'WorkflowRun\']/property[@name=\'description\']/@value</returnfield>"; |
19 | 19 |
queryString += "<returnfield>/property[@name=\'WorkflowRun\']/property[@name=\'startTime\']/@value</returnfield>"; |
20 | 20 |
queryString += "<returnfield>/property[@name=\'WorkflowRun\']/property[@name=\'workflowLSID\']/@value</returnfield>"; |
21 |
queryString += "<returnfield>/property[@name=\'WorkflowRun\']/property[@name=\'status\']/@value</returnfield>";
|
|
21 |
queryString += "<returnfield>/property[@name=\'WorkflowRun\']/property[@name=\'tpcStatus\']/@value</returnfield>";
|
|
22 | 22 |
queryString += "<returnfield>/property[@name=\'WorkflowRun\']/property[@name=\'workflowName\']/@value</returnfield>"; |
23 | 23 |
queryString += "<returnfield>/property[@name=\'WorkflowRun\']/property[@name=\'pdfReport\']/@value</returnfield>"; |
24 | 24 |
queryString += "<returnfield>/property[@name=\'WorkflowRun\']/property[@name=\'htmlReport\']/@value</returnfield>"; |
... | ... | |
45 | 45 |
queryField.value = queryString; |
46 | 46 |
} |
47 | 47 |
|
48 |
/* |
|
49 |
* Generate individual query terms for all the search input fields in a search |
|
50 |
* form. There must be a case for each search field handle explicitly below. |
|
51 |
* This assumes: |
|
52 |
* -- search input fields have an ID that starts with sf- |
|
53 |
* -- if there is a search mode dropdown for an input field in the form, it's ID |
|
54 |
* should use the same convention as the input field, but start with sm- |
|
55 |
* (i.e. the search mode input for the sf-firstname input would be sm-firstname) |
|
56 |
*/ |
|
48 | 57 |
function getQueryTerm(sfElement) { |
49 | 58 |
var baseId = sfElement.id.substring(3, sfElement.id.length); |
50 | 59 |
var searchMode = "contains"; |
... | ... | |
94 | 103 |
pathExpr += "<value>workflowLSID</value>"; |
95 | 104 |
pathExpr += "<pathexpr>property/property/@name</pathexpr>"; |
96 | 105 |
pathExpr += "</queryterm>"; |
97 |
pathExpr += "<queryterm casesensitive='false' searchmode='" + searchMode + "'>"; |
|
98 |
pathExpr += "<value>" + sfElement.value + "</value>"; |
|
99 |
pathExpr += "<pathexpr>property/property/@value</pathexpr>"; |
|
100 |
pathExpr += "</queryterm>"; |
|
106 |
// pathExpr += "<queryterm casesensitive='false' searchmode='" + searchMode + "'>";
|
|
107 |
// pathExpr += "<value>" + sfElement.value + "</value>";
|
|
108 |
// pathExpr += "<pathexpr>property/property/@value</pathexpr>";
|
|
109 |
// pathExpr += "</queryterm>";
|
|
101 | 110 |
} else if (sfElement.name == 'workflow-run-id') { |
102 | 111 |
pathExpr += "<queryterm casesensitive='false' searchmode='" + searchMode + "'>"; |
103 | 112 |
pathExpr += "<value>" + sfElement.value + "</value>"; |
... | ... | |
114 | 123 |
return pathExpr; |
115 | 124 |
} |
116 | 125 |
|
117 |
function getResultsSection(url, formId, divId) { |
|
118 |
var submitResults = submitFormIntoDiv(url, formId, divId); |
|
119 |
} |
|
120 |
|
|
121 |
function showWorkflowRuns(workflowId, workflowRunPage) { |
|
122 |
url = document.URL + '/../' + workflowRunPage + '?workflowid=' + workflowId; |
|
123 |
//alert('new url: ' + url); |
|
124 |
window.location = url; |
|
125 |
} |
|
126 |
|
|
127 | 126 |
|
lib/style/common/searchWorkflowRunResultset.xsl | ||
---|---|---|
39 | 39 |
<xsl:template match="/"> |
40 | 40 |
<div class="result-header-section"> |
41 | 41 |
<div class="result-header">TPC Workflow Runs</div> |
42 |
<div class="result-header-emphasis">(<xsl:number value="count(resultset/document)" /> |
|
43 |
<xsl:if test="count(resultset/document) != 1"> items</xsl:if> |
|
44 |
<xsl:if test="count(resultset/document) = 1"> item</xsl:if> |
|
45 |
found) |
|
46 |
</div> |
|
47 | 42 |
</div> |
48 | 43 |
<div class="row row-header" > |
49 | 44 |
<div class="col col1">TPC Workflow Name</div> |
... | ... | |
68 | 63 |
</div> |
69 | 64 |
<div class="col col2"> |
70 | 65 |
<xsl:choose> |
71 |
<xsl:when test="not(./param[@name="/property[@name='WorkflowRun']/property[@name='status']/@value"])" >
|
|
66 |
<xsl:when test="not(./param[@name="/property[@name='WorkflowRun']/property[@name='tpcStatus']/@value"])" >
|
|
72 | 67 |
unknown |
73 | 68 |
</xsl:when> |
74 | 69 |
<xsl:otherwise> |
75 |
<xsl:value-of select='./param[@name="/property[@name='WorkflowRun']/property[@name='status']/@value"]' />
|
|
70 |
<xsl:value-of select='./param[@name="/property[@name='WorkflowRun']/property[@name='tpcStatus']/@value"]' />
|
|
76 | 71 |
</xsl:otherwise> |
77 | 72 |
</xsl:choose> |
78 | 73 |
</div> |
src/edu/ucsb/nceas/metacat/workflow/WorkflowJob.java | ||
---|---|---|
42 | 42 |
public class WorkflowJob implements InterruptableJob { |
43 | 43 |
|
44 | 44 |
private static Logger logMetacat = Logger.getLogger(WorkflowJob.class); |
45 |
|
|
45 |
|
|
46 |
/** |
|
47 |
* Required method that is called when the job is run by the scheduler. |
|
48 |
* |
|
49 |
* @param executionContext |
|
50 |
* the context information for this job |
|
51 |
*/ |
|
46 | 52 |
public void execute(JobExecutionContext executionContext) throws JobExecutionException { |
47 | 53 |
try { |
54 |
// have to be able to get the job detail |
|
48 | 55 |
JobDetail jobDetail = executionContext.getJobDetail(); |
49 | 56 |
if (jobDetail == null) { |
50 | 57 |
throw new JobExecutionException("WorkflowJob.execute - Could not get job detail from execution context"); |
51 | 58 |
} |
52 | 59 |
|
60 |
// have to be able to get the job data map from the job detail |
|
53 | 61 |
JobDataMap jobDataMap = jobDetail.getJobDataMap(); |
54 | 62 |
if (jobDataMap == null) { |
55 | 63 |
throw new JobExecutionException("WorkflowJob.execute - Could not get job data map from job detail"); |
56 | 64 |
} |
57 | 65 |
|
66 |
// the kar lsid must be part of the job data map |
|
58 | 67 |
String karLSID = jobDataMap.getString("karid"); |
59 | 68 |
if (karLSID == null) { |
60 | 69 |
throw new JobExecutionException("WorkflowJob.execute - Could not get kar LSID from job data map"); |
61 | 70 |
} |
62 | 71 |
|
72 |
// Locate service |
|
63 | 73 |
logMetacat.debug("WorkflowJob.execute - Getting serviceLocator"); |
64 | 74 |
KeplerWebServiceLocator serviceLocator = new KeplerWebServiceLocator(); |
65 | 75 |
|
76 |
// get endpoint service |
|
66 | 77 |
logMetacat.debug("WorkflowJob.execute - Getting service"); |
67 | 78 |
KeplerWebServicePortType serviceEndpoint = serviceLocator.getKeplerWebServiceHttpSoap11Endpoint(); |
68 | 79 |
|
80 |
// call execute against remote endpoint |
|
69 | 81 |
logMetacat.debug("WorkflowJob.execute - Executing with kar lsid:" + karLSID); |
70 | 82 |
String status = serviceEndpoint.execute(karLSID); |
71 | 83 |
//String status = serviceEndpoint.getStatus(karLSID); |
src/edu/ucsb/nceas/metacat/workflow/WorkflowScheduler.java | ||
---|---|---|
1 | 1 |
/** |
2 | 2 |
* '$RCSfile$' |
3 |
* Purpose: A Class that handles scheduling tasks
|
|
3 |
* Purpose: A Class that handles scheduling workflow jobs
|
|
4 | 4 |
* Copyright: 2009 Regents of the University of California and the |
5 | 5 |
* National Center for Ecological Analysis and Synthesis |
6 | 6 |
* Authors: Michael Daigle |
... | ... | |
31 | 31 |
import java.text.ParseException; |
32 | 32 |
import java.util.Calendar; |
33 | 33 |
import java.util.Date; |
34 |
import java.util.Enumeration; |
|
35 | 34 |
import java.util.Hashtable; |
36 | 35 |
import java.util.HashMap; |
37 | 36 |
|
... | ... | |
54 | 53 |
import edu.ucsb.nceas.metacat.util.RequestUtil; |
55 | 54 |
import edu.ucsb.nceas.shared.AccessException; |
56 | 55 |
|
56 |
/** |
|
57 |
* @author daigle |
|
58 |
* |
|
59 |
*/ |
|
60 |
/** |
|
61 |
* @author daigle |
|
62 |
* |
|
63 |
*/ |
|
57 | 64 |
public class WorkflowScheduler extends BaseScheduler { |
58 | 65 |
|
59 | 66 |
private static WorkflowScheduler workflowScheduler = null; |
... | ... | |
80 | 87 |
return workflowScheduler; |
81 | 88 |
} |
82 | 89 |
|
90 |
/** |
|
91 |
* Scheduling a workflow |
|
92 |
* |
|
93 |
* @param request |
|
94 |
* the servlet request object |
|
95 |
* @param response |
|
96 |
* the servlet response object |
|
97 |
* @param params |
|
98 |
* the request parameters |
|
99 |
* @param username |
|
100 |
* the user |
|
101 |
* @param groups |
|
102 |
* the user's group |
|
103 |
*/ |
|
83 | 104 |
public void scheduleJob(HttpServletRequest request, HttpServletResponse response, |
84 | 105 |
Hashtable<String, String[]> params, String username, |
85 | 106 |
String[] groups) throws MetacatSchedulerException { |
... | ... | |
92 | 113 |
try { |
93 | 114 |
SchedulerService schedulerService = SchedulerService.getInstance(); |
94 | 115 |
|
95 |
if (delays != null && delays.length > 0) { |
|
96 |
startCal = schedulerService.getStartDateFromDelay(delays[0]); |
|
97 |
} else if (startTimes != null && startTimes.length > 0) { |
|
116 |
// get start time or delay. Start time takes precidence if both exist. |
|
117 |
if (startTimes != null && startTimes.length > 0) { |
|
98 | 118 |
SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss z"); |
99 | 119 |
Date startDate = dateFormat.parse(startTimes[0]); |
100 | 120 |
startCal = Calendar.getInstance(); |
101 | 121 |
startCal.setTime(startDate); |
122 |
} else if (delays != null && delays.length > 0) { |
|
123 |
startCal = schedulerService.getStartDateFromDelay(delays[0]); |
|
102 | 124 |
} else { |
103 | 125 |
// if delay and starttime were not provided, set date to now. |
104 | 126 |
startCal = Calendar.getInstance(); |
105 | 127 |
} |
106 | 128 |
|
129 |
// interval value must exist |
|
107 | 130 |
String intervalValues[] = params.get("intervalvalue"); |
108 | 131 |
if (intervalValues == null || intervalValues.length == 0) { |
109 | 132 |
throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - intervalvalue field must be populated " |
... | ... | |
112 | 135 |
String intervalStrValue = intervalValues[0]; |
113 | 136 |
int intervalValue = Integer.parseInt(intervalStrValue); |
114 | 137 |
|
138 |
// interval unit must exist |
|
115 | 139 |
String intervalUnits[] = params.get("intervalunit"); |
116 | 140 |
if (intervalUnits == null || intervalUnits.length == 0) { |
117 | 141 |
throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - intervalunit field must be populated " |
... | ... | |
119 | 143 |
} |
120 | 144 |
String intervalUnit = intervalUnits[0]; |
121 | 145 |
|
122 |
Enumeration<String> paramNames = params.keys(); |
|
123 |
while (paramNames.hasMoreElements()) { |
|
124 |
String paramName = paramNames.nextElement(); |
|
125 |
if (paramName.startsWith("jobparam_")) { |
|
126 |
jobParams.put(paramName.substring(9), params.get(paramName)[0]); |
|
127 |
} |
|
146 |
// workflow id unit must exist. Add to job params |
|
147 |
String workflowids[] = params.get("workflowid"); |
|
148 |
if (workflowids == null || workflowids.length == 0) { |
|
149 |
throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - workflowid field must be populated " |
|
150 |
+ "in scheduler parameters when scheduling job."); |
|
128 | 151 |
} |
152 |
jobParams.put("workflowid", workflowids[0]); |
|
153 |
|
|
154 |
// kar id must exist. Add to job params |
|
155 |
String karids[] = params.get("karid"); |
|
156 |
if (karids == null || karids.length == 0) { |
|
157 |
throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - karid field must be populated " |
|
158 |
+ "in scheduler parameters when scheduling job."); |
|
159 |
} |
|
160 |
jobParams.put("karid", karids[0]); |
|
161 |
|
|
162 |
|
|
163 |
// workflow name unit must exist. Add to job params |
|
164 |
String workflownames[] = params.get("workflowname"); |
|
165 |
if (workflownames == null || workflownames.length == 0) { |
|
166 |
throw new MetacatSchedulerException("WorkflowScheduler.scheduleJob - workflowname field must be populated " |
|
167 |
+ "in scheduler parameters when scheduling job."); |
|
168 |
} |
|
169 |
jobParams.put("workflowname", workflownames[0]); |
|
129 | 170 |
|
130 | 171 |
String jobName = WORKFLOW_JOB_GROUP |
131 | 172 |
+ Calendar.getInstance().getTimeInMillis(); |
132 | 173 |
|
174 |
// Schedule the job |
|
133 | 175 |
String xmlResult = schedulerService.scheduleJob(jobName, startCal, intervalValue, intervalUnit, |
134 | 176 |
WORKFLOW_JOB_CLASS, WORKFLOW_JOB_GROUP, jobParams, username, groups); |
135 | 177 |
|
178 |
// if there is a forwardto param on the request, then send the user to the page |
|
179 |
// referenced in that param, otherwise, just send the xml back. |
|
136 | 180 |
String forwardtos[] = params.get("forwardto"); |
137 | 181 |
String forwardto = null; |
138 | 182 |
if (forwardtos != null && forwardtos.length > 0) { |
... | ... | |
167 | 211 |
} |
168 | 212 |
} |
169 | 213 |
|
214 |
/** |
|
215 |
* Unschedule a job |
|
216 |
* |
|
217 |
* @param request |
|
218 |
* the servlet request object |
|
219 |
* @param response |
|
220 |
* the servlet response object |
|
221 |
* @param params |
|
222 |
* the request parameters |
|
223 |
* @param username |
|
224 |
* the user |
|
225 |
* @param groups |
|
226 |
* the user's group |
|
227 |
*/ |
|
170 | 228 |
public void unScheduleJob(HttpServletRequest request, HttpServletResponse response, |
171 | 229 |
Hashtable<String, String[]> params, String username, String[] groups) |
172 | 230 |
throws MetacatSchedulerException { |
173 | 231 |
try { |
232 |
// workflow job id must exist |
|
174 | 233 |
String jobNames[] = params.get("workflowjobid"); |
175 | 234 |
if (jobNames == null || jobNames.length == 0) { |
176 | 235 |
throw new MetacatSchedulerException("SchedulerService.unScheduleJob - workflowjobid " |
... | ... | |
178 | 237 |
} |
179 | 238 |
String jobName = jobNames[0]; |
180 | 239 |
|
240 |
// unschedule the job |
|
181 | 241 |
SchedulerService schedulerService = SchedulerService.getInstance(); |
182 | 242 |
String xmlResult = schedulerService.unScheduleJob(jobName, username, groups); |
183 | 243 |
|
244 |
|
|
184 | 245 |
String forwardtos[] = params.get("forwardto"); |
185 | 246 |
String forwardto = null; |
186 | 247 |
if (forwardtos != null && forwardtos.length > 0) { |
187 | 248 |
forwardto = forwardtos[0]; |
188 | 249 |
} |
189 | 250 |
|
251 |
// if there is a forwardto param on the request, then send the user to the page |
|
252 |
// referenced in that param, otherwise, just send the xml back. |
|
190 | 253 |
if (forwardto != null) { |
191 | 254 |
String qformats[] = params.get("qformat"); |
192 | 255 |
String qformat = null; |
... | ... | |
197 | 260 |
ScheduledJobAccess jobAccess = new ScheduledJobAccess(); |
198 | 261 |
ScheduledJobDAO jobDAO = jobAccess.getJobByName(jobName); |
199 | 262 |
|
263 |
// we need to include the workflow id in the forward url |
|
200 | 264 |
String workflowId = null; |
201 | 265 |
ScheduledJobParamDAO jobParamDAO = jobDAO.getJobParam("workflowid"); |
202 | 266 |
if (jobParamDAO != null) { |
... | ... | |
221 | 285 |
} |
222 | 286 |
} |
223 | 287 |
|
288 |
/** |
|
289 |
* reschedule job |
|
290 |
* |
|
291 |
* @param request |
|
292 |
* the servlet request object |
|
293 |
* @param response |
|
294 |
* the servlet response object |
|
295 |
* @param params |
|
296 |
* the request parameters |
|
297 |
* @param username |
|
298 |
* the user |
|
299 |
* @param groups |
|
300 |
* the user's group |
|
301 |
*/ |
|
224 | 302 |
public void reScheduleJob(HttpServletRequest request, HttpServletResponse response, |
225 | 303 |
Hashtable<String, String[]> params, String username, |
226 | 304 |
String[] groups) throws MetacatSchedulerException { |
227 | 305 |
|
228 | 306 |
try { |
229 |
String jobNames[] = params.get("workflowjobid");
|
|
230 |
|
|
307 |
// workflow job id must exist
|
|
308 |
String jobNames[] = params.get("workflowjobid"); |
|
231 | 309 |
if (jobNames == null || jobNames.length == 0) { |
232 | 310 |
throw new MetacatSchedulerException("WorkflowScheduler.reScheduleJob - workflowjobid field must be populated " |
233 | 311 |
+ "in scheduler parameters when rescheduling job."); |
234 |
} |
|
235 |
|
|
312 |
} |
|
236 | 313 |
String jobName = jobNames[0]; |
237 | 314 |
|
238 | 315 |
ScheduledJobAccess jobAccess = new ScheduledJobAccess(); |
239 | 316 |
ScheduledJobDAO jobDAO = jobAccess.getJobByName(jobName); |
240 | 317 |
|
318 |
// reschedule the job |
|
241 | 319 |
SchedulerService schedulerService = SchedulerService.getInstance(); |
242 | 320 |
String result = schedulerService.rescheduleJob(jobDAO, username, groups); |
243 | 321 |
|
322 |
// if there is a forwardto param on the request, then send the user to the page |
|
323 |
// referenced in that param, otherwise, just send the xml back. |
|
244 | 324 |
String forwardtos[] = params.get("forwardto"); |
245 | 325 |
String forwardto = null; |
246 | 326 |
if (forwardtos != null && forwardtos.length > 0) { |
... | ... | |
254 | 334 |
qformat = qformats[0]; |
255 | 335 |
} |
256 | 336 |
|
337 |
// we need to include the workflow id in the forward url |
|
257 | 338 |
String workflowId = null; |
258 | 339 |
ScheduledJobParamDAO jobParamDAO = jobDAO.getAllJobParams().get("workflowid"); |
259 | 340 |
if (jobParamDAO != null) { |
... | ... | |
280 | 361 |
} |
281 | 362 |
} |
282 | 363 |
|
364 |
/** |
|
365 |
* delete job - to be implemented |
|
366 |
*/ |
|
283 | 367 |
public void deleteJob(HttpServletRequest request, HttpServletResponse response, |
284 | 368 |
Hashtable<String, String[]> params, String username, String[] groups) throws MetacatSchedulerException { |
285 | 369 |
|
286 | 370 |
} |
287 | 371 |
|
372 |
/** |
|
373 |
* get job information for a given workflow in xml format |
|
374 |
* |
|
375 |
* @param request |
|
376 |
* the servlet request object |
|
377 |
* @param response |
|
378 |
* the servlet response object |
|
379 |
* @param params |
|
380 |
* the request parameters |
|
381 |
* @param username |
|
382 |
* the user |
|
383 |
* @param groups |
|
384 |
* the user's group |
|
385 |
*/ |
|
288 | 386 |
public void getJobs(HttpServletRequest request, HttpServletResponse response, |
289 | 387 |
Hashtable<String, String[]> params, String username, String[] groups) throws MetacatSchedulerException { |
290 | 388 |
|
... | ... | |
301 | 399 |
} |
302 | 400 |
|
303 | 401 |
try { |
402 |
// get the job info in xml format |
|
304 | 403 |
String xmlResult = SchedulerService.getInstance().getJobsInfoXML(WORKFLOW_JOB_GROUP, "workflowid", workFlowId); |
305 | 404 |
logMetacat.debug("WorkflowScheduler.getJobs - xmlResult: " + xmlResult); |
306 | 405 |
|
src/edu/ucsb/nceas/metacat/scheduler/ScheduledJobDAO.java | ||
---|---|---|
1 | 1 |
/** |
2 | 2 |
* '$RCSfile$' |
3 |
* Purpose: A Class that holds the data from the scheduled_task
|
|
3 |
* Purpose: A Class that holds the data from the scheduled_job
|
|
4 | 4 |
* table in the database. |
5 | 5 |
* Copyright: 2009 Regents of the University of California and the |
6 | 6 |
* National Center for Ecological Analysis and Synthesis |
... | ... | |
34 | 34 |
|
35 | 35 |
public class ScheduledJobDAO extends BaseDAO { |
36 | 36 |
|
37 |
|
|
38 |
public static String SECONDLY = "secondly"; |
|
39 |
public static String MINUTELY = "minutely"; |
|
40 |
public static String HOURLY = "hourly"; |
|
41 |
public static String DAILY = "daily"; |
|
42 |
public static String WEEKLY = "weekly"; |
|
37 |
public static String SECONDLY = "s"; |
|
38 |
public static String MINUTELY = "m"; |
|
39 |
public static String HOURLY = "h"; |
|
40 |
public static String DAILY = "d"; |
|
41 |
public static String WEEKLY = "w"; |
|
43 | 42 |
|
44 | 43 |
private String _name; |
45 | 44 |
private String _triggerName; |
... | ... | |
50 | 49 |
private String _intervalUnit; |
51 | 50 |
private HashMap<String, ScheduledJobParamDAO> _jobParams = new HashMap<String, ScheduledJobParamDAO>(); |
52 | 51 |
|
52 |
// get the name |
|
53 | 53 |
public String getName() { |
54 | 54 |
return _name; |
55 | 55 |
} |
56 | 56 |
|
57 |
// set the name |
|
57 | 58 |
public void setName(String name) { |
58 | 59 |
_name = name; |
59 | 60 |
} |
60 | 61 |
|
62 |
// get the trigger name |
|
61 | 63 |
public String getTriggerName() { |
62 | 64 |
return _triggerName; |
63 | 65 |
} |
64 | 66 |
|
67 |
// set the trigger name |
|
65 | 68 |
public void setTriggerName(String triggerName) { |
66 | 69 |
_triggerName = triggerName; |
67 | 70 |
} |
68 | 71 |
|
72 |
// get the group name |
|
69 | 73 |
public String getGroupName() { |
70 | 74 |
return _groupName; |
71 | 75 |
} |
72 | 76 |
|
77 |
// set the group name |
|
73 | 78 |
public void setGroupName(String groupName) { |
74 | 79 |
_groupName = groupName; |
75 | 80 |
} |
76 | 81 |
|
82 |
// get the class name |
|
77 | 83 |
public String getClassName() { |
78 | 84 |
return _className; |
79 | 85 |
} |
80 | 86 |
|
87 |
// set the class name |
|
81 | 88 |
public void setClassName(String className) { |
82 | 89 |
_className = className; |
83 | 90 |
} |
84 | 91 |
|
92 |
// get the start time |
|
85 | 93 |
public Timestamp getStartTime() { |
86 | 94 |
return _startTime; |
87 | 95 |
} |
88 | 96 |
|
97 |
// set the start time |
|
89 | 98 |
public void setStartTime(Timestamp startTime) { |
90 | 99 |
_startTime = startTime; |
91 | 100 |
} |
92 | 101 |
|
102 |
// get the interval value |
|
93 | 103 |
public int getIntervalValue() { |
94 | 104 |
return _intervalValue; |
95 | 105 |
} |
96 | 106 |
|
107 |
// set the interval value |
|
97 | 108 |
public void setIntervalValue(int intervalValue) { |
98 | 109 |
_intervalValue = intervalValue; |
99 | 110 |
} |
100 | 111 |
|
112 |
// get the interval unit |
|
101 | 113 |
public String getIntervalUnit() { |
102 | 114 |
return _intervalUnit; |
103 | 115 |
} |
104 | 116 |
|
117 |
// set the interval unit |
|
105 | 118 |
public void setIntervalUnit(String intervalUnit) { |
106 | 119 |
_intervalUnit = intervalUnit; |
107 | 120 |
} |
108 | 121 |
|
122 |
// get the job param with the given key |
|
109 | 123 |
public ScheduledJobParamDAO getJobParam(String key) { |
110 | 124 |
return _jobParams.get(key); |
111 | 125 |
} |
112 | 126 |
|
127 |
// get all the job params for this job |
|
113 | 128 |
public HashMap<String, ScheduledJobParamDAO> getAllJobParams() { |
114 | 129 |
return _jobParams; |
115 | 130 |
} |
116 | 131 |
|
132 |
// add a job param to this job |
|
117 | 133 |
public void addJobParam(ScheduledJobParamDAO jobParamDAO) { |
118 | 134 |
_jobParams.put(jobParamDAO.getKey(), jobParamDAO); |
119 | 135 |
} |
src/edu/ucsb/nceas/metacat/scheduler/SchedulerService.java | ||
---|---|---|
73 | 73 |
return schedulerService; |
74 | 74 |
} |
75 | 75 |
|
76 |
// this is a refreshable class |
|
76 | 77 |
public boolean refreshable() { |
77 | 78 |
return true; |
78 | 79 |
} |
79 |
|
|
80 |
|
|
81 |
// do the refresh |
|
80 | 82 |
protected void doRefresh() throws ServiceException { |
81 | 83 |
stop(); |
84 |
start(); |
|
82 | 85 |
} |
83 | 86 |
|
87 |
// initialize the service |
|
84 | 88 |
protected void start() throws ServiceException { |
85 | 89 |
try { |
90 |
// get the Quartz scheduler factory |
|
86 | 91 |
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory(); |
87 | 92 |
|
93 |
// get the scheduler |
|
88 | 94 |
sched = schedFact.getScheduler(); |
89 | 95 |
sched.start(); |
90 | 96 |
|
97 |
// get all existing jobs from the database |
|
91 | 98 |
ScheduledJobAccess jobAccess = new ScheduledJobAccess(); |
92 | 99 |
HashMap<Long, ScheduledJobDAO> allJobsMap = jobAccess.getAllJobs(null); |
93 | 100 |
|
101 |
// reschedule each job that is in a SCHEDULED state. |
|
94 | 102 |
for (Long jobId : allJobsMap.keySet()) { |
95 | 103 |
ScheduledJobDAO jobDAO = allJobsMap.get(jobId); |
96 | 104 |
String[] groups = {"scheduler_group"}; |
97 | 105 |
if (jobDAO.getStatus().equals(StatusUtil.SCHEDULED)) { |
106 |
// send false as the last param so the reschedule method will not |
|
107 |
// complain that the job is already in a SCHEDULED state. |
|
98 | 108 |
rescheduleJob(jobDAO, "scheduler_user", groups, false); |
99 | 109 |
} |
100 | 110 |
} |
101 | 111 |
|
102 | 112 |
} catch (AccessException ae) { |
103 |
throw new ServiceException("DB Access issue when starting scheduler: ", ae); |
|
113 |
throw new ServiceException("SchedulerService.start - DB Access issue when starting scheduler: ", ae);
|
|
104 | 114 |
} catch (SchedulerException se) { |
105 |
throw new ServiceException("Scheduler engine issue when starting scheduler: " + se.getMessage()); |
|
115 |
throw new ServiceException("SchedulerService.start - Scheduler engine issue when starting scheduler: " + se.getMessage());
|
|
106 | 116 |
} |
107 | 117 |
} |
108 | 118 |
|
119 |
// Stop the scheduler |
|
109 | 120 |
protected void stop() throws ServiceException { |
110 | 121 |
try { |
111 | 122 |
sched.shutdown(true); |
112 | 123 |
sched = null; |
113 | 124 |
} catch (SchedulerException se) { |
114 |
throw new ServiceException("Could not shut down scheduler: " + se.getMessage()); |
|
125 |
throw new ServiceException("SchedulerService.stop - Could not shut down scheduler: " + se.getMessage());
|
|
115 | 126 |
} |
116 | 127 |
} |
117 | 128 |
|
129 |
// this will eventually return the scheduler status |
|
118 | 130 |
protected Vector<String> getStatus() throws ServiceException { |
119 | 131 |
return new Vector<String>(); |
120 | 132 |
} |
121 | 133 |
|
134 |
/** |
|
135 |
* Schedule a job |
|
136 |
* |
|
137 |
* @param jobDAO |
|
138 |
* the job data object to schedule |
|
139 |
* @param username |
|
140 |
* the user that we will use to schedule |
|
141 |
* @param groups |
|
142 |
* the user group that we will use to schedule |
|
143 |
* @return a message saying that the job was scheduled |
|
144 |
*/ |
|
122 | 145 |
public String scheduleJob(ScheduledJobDAO jobDAO, String username, String[] groups) throws ServiceException { |
123 | 146 |
|
147 |
// convert the start time to a calendar object |
|
124 | 148 |
Calendar startTimeCal = Calendar.getInstance(); |
125 | 149 |
startTimeCal.setTime(jobDAO.getStartTime()); |
126 | 150 |
|
151 |
// extract the job parameters from their data objects and put into a string map |
|
127 | 152 |
HashMap<String, String> jobParams = new HashMap<String, String>(); |
128 | 153 |
HashMap<String, ScheduledJobParamDAO> jobParamDAOs = jobDAO.getAllJobParams(); |
129 | 154 |
for (String paramName : jobParamDAOs.keySet()) { |
130 | 155 |
jobParams.put(paramName, jobParamDAOs.get(paramName).getValue()); |
131 | 156 |
} |
132 | 157 |
|
158 |
// schedule the job |
|
133 | 159 |
return scheduleJob(jobDAO.getName(), startTimeCal, jobDAO.getIntervalValue(), jobDAO.getIntervalUnit(), |
134 | 160 |
jobDAO.getClassName(), jobDAO.getGroupName(), jobParams, username, groups); |
135 | 161 |
} |
136 | 162 |
|
163 |
/** |
|
164 |
* schedule a job |
|
165 |
* |
|
166 |
* @param jobName |
|
167 |
* the name of the job |
|
168 |
* @param startCal |
|
169 |
* a calendar holding the start date of the job |
|
170 |
* @param intervalValue |
|
171 |
* the run interval for the job |
|
172 |
* @param intervalUnit |
|
173 |
* the unit of the run interval for the job |
|
174 |
* @param jobClassName |
|
175 |
* the job class name |
|
176 |
* @param jobGroup |
|
177 |
* the job group name |
|
178 |
* @param jobParams |
|
179 |
* a map of additional job parameters |
|
180 |
* @param username |
|
181 |
* the user name |
|
182 |
* @param groups |
|
183 |
* the user's group name |
|
184 |
* @return a message saying that the job was scheduled |
|
185 |
*/ |
|
137 | 186 |
public String scheduleJob(String jobName, Calendar startCal, int intervalValue, String intervalUnit, |
138 | 187 |
String jobClassName, String jobGroup, HashMap<String, String> jobParams, |
139 | 188 |
String username, String[] groups) throws ServiceException { |
... | ... | |
146 | 195 |
+ jobClassName + " : " + cnfe.getMessage()); |
147 | 196 |
} |
148 | 197 |
|
149 |
logMetacat.info("Scheduling job -- name: " + jobName + ", class: " + jobClassName |
|
198 |
logMetacat.info("SchedulerService.scheduleJob - Scheduling job -- name: " + jobName + ", class: " + jobClassName
|
|
150 | 199 |
+ ", start time: " + startCal.toString() + ", interval value: " + intervalValue |
151 | 200 |
+ ", interval unit: " + intervalUnit); |
152 | 201 |
|
202 |
// start the job in the job scheduler |
|
153 | 203 |
startJob(jobName, startCal, intervalValue, intervalUnit, jobClass, jobGroup, jobParams); |
154 | 204 |
|
205 |
// get a database access object and create the job in the database |
|
155 | 206 |
try { |
156 | 207 |
ScheduledJobAccess jobAccess = new ScheduledJobAccess(); |
157 | 208 |
jobAccess.createJob(jobName, jobName, jobGroup, jobClass, startCal, intervalValue, intervalUnit, jobParams); |
... | ... | |
160 | 211 |
deleteJob(jobName, username, groups); |
161 | 212 |
} catch (Exception e) { |
162 | 213 |
// Not much we can do here but log this |
163 |
logMetacat.error("An access exception was thrown when writing job: " + jobName |
|
214 |
logMetacat.error("SchedulerService.scheduleJob - An access exception was thrown when writing job: " + jobName
|
|
164 | 215 |
+ "to the db, and another exception was thrown when trying to remove the " |
165 | 216 |
+ "job from the scheduler. The db and scheduler may be out of sync: " + e.getMessage()); |
166 | 217 |
} |
... | ... | |
170 | 221 |
return "Scheduled: " + jobName; |
171 | 222 |
} |
172 | 223 |
|
173 |
|
|
174 |
|
|
224 |
/** |
|
225 |
* Unschedule a job. This removed it from the scheduler in memory and |
|
226 |
* changed it's status to unscheduled in the database. |
|
227 |
* |
|
228 |
* @param jobName |
|
229 |
* the name of the job to unschedule |
|
230 |
* @param username |
|
231 |
* the user name |
|
232 |
* @param groups |
|
233 |
* the user's group name |
|
234 |
* @return a message saying the job was unscheduled |
|
235 |
*/ |
|
175 | 236 |
public String unScheduleJob(String jobName, String username, |
176 | 237 |
String[] groups) throws ServiceException { |
177 | 238 |
try { |
... | ... | |
182 | 243 |
+ "not find job with name: " + jobName); |
183 | 244 |
} |
184 | 245 |
|
246 |
// remove the job from the scheduler |
|
185 | 247 |
sched.deleteJob(jobDAO.getName(), jobDAO.getGroupName()); |
186 | 248 |
|
249 |
// change the status of the job to unscheduled in the database. |
|
187 | 250 |
jobDAO.setStatus(StatusUtil.UNSCHEDULED); |
188 | 251 |
jobAccess.updateJobStatus(jobDAO); |
189 | 252 |
} catch (SchedulerException se) { |
... | ... | |
197 | 260 |
return "Unscheduled: " + jobName; |
198 | 261 |
} |
199 | 262 |
|
263 |
/** |
|
264 |
* Reschedule a job. This call will always check to make sure the status is not SCHEDULED |
|
265 |
* @param jobDAO the job data object holding the information about the job to reschedule |
|
266 |
* @param username |
|
267 |
* the user name |
|
268 |
* @param groups |
|
269 |
* the user's group name |
|
270 |
* @return a message saying that the job was rescheduled |
|
271 |
*/ |
|
200 | 272 |
public String rescheduleJob(ScheduledJobDAO jobDAO, String username, String[] groups) throws ServiceException { |
201 | 273 |
return rescheduleJob(jobDAO, username, groups, true); |
202 | 274 |
} |
203 | 275 |
|
276 |
/** |
|
277 |
* Reschedule a job. |
|
278 |
* |
|
279 |
* @param jobDAO |
|
280 |
* the job data object holding the information about the job to |
|
281 |
* reschedule |
|
282 |
* @param username |
|
283 |
* the user name |
|
284 |
* @param groups |
|
285 |
* the user's group name |
|
286 |
* @param checkStatus |
|
287 |
* if set to true, the method will check to make sure the status |
|
288 |
* is UNSCHEDULED before restarting. Otherwise, the method will |
|
289 |
* not check. This is so that we can restart a service at startup |
|
290 |
* that was running when metacat was shut down. |
|
291 |
* @return a message saying that the job was rescheduled |
|
292 |
*/ |
|
204 | 293 |
public String rescheduleJob(ScheduledJobDAO jobDAO, String username, String[] groups, boolean checkStatus) throws ServiceException { |
205 | 294 |
|
206 | 295 |
try { |
... | ... | |
210 | 299 |
throw new ServiceException("SchedulerService.reScheduleJob - Cannot reschedule nonexistant job."); |
211 | 300 |
} |
212 | 301 |
|
302 |
// if we are checking status, make sure the job is in an UNSCHEDULED state in the db |
|
213 | 303 |
if (checkStatus && !jobDAO.getStatus().equals(StatusUtil.UNSCHEDULED)) { |
214 | 304 |
throw new ServiceException("SchedulerService.reScheduleJob - Cannot reschedule a job with status: " |
215 | 305 |
+ jobDAO.getStatus() + ". Status must be 'unscheduled'."); |
... | ... | |
237 | 327 |
+ ", start time: " + startCal.toString() + ", interval value: " + jobDAO.getIntervalValue() |
238 | 328 |
+ ", interval unit: " + jobDAO.getIntervalUnit()); |
239 | 329 |
|
330 |
// start the job in the scheduler |
|
240 | 331 |
startJob(jobDAO.getName(), startCal, jobDAO.getIntervalValue(), jobDAO.getIntervalUnit(), jobClass, jobDAO.getGroupName(), jobParams); |
241 | 332 |
|
333 |
// update the status in the database |
|
242 | 334 |
jobDAO.setStatus(StatusUtil.SCHEDULED); |
243 | 335 |
jobAccess.updateJobStatus(jobDAO); |
244 | 336 |
|
... | ... | |
250 | 342 |
return "Resheduled: " + jobDAO.getName(); |
251 | 343 |
} |
252 | 344 |
|
345 |
/** |
|
346 |
* Remove the job from the scheduler and set the job status to deleted in the database |
|
347 |
* @param jobDAO |
|
348 |
* the job data object holding the information about the job to |
|
349 |
* delete |
|
350 |
* @param username |
|
351 |
* the user name |
|
352 |
* @param groups |
|
353 |
* the user's group name |
|
354 |
* @return a message saying that the job was deleted |
|
355 |
*/ |
|
253 | 356 |
public String deleteJob(String jobName, String username, |
254 | 357 |
String[] groups) throws ServiceException { |
255 | 358 |
|
... | ... | |
274 | 377 |
return "Deleted: " + jobName; |
275 | 378 |
} |
276 | 379 |
|
380 |
/** |
|
381 |
* Get information about the job in XML format |
|
382 |
* |
|
383 |
* @param jobId |
|
384 |
* the job for which we want the information |
|
385 |
* @return an XML representation of the job |
|
386 |
*/ |
|
277 | 387 |
public String getJobInfoXML(Long jobId) throws ServiceException { |
278 | 388 |
String jobInfoXML = ""; |
279 | 389 |
|
... | ... | |
292 | 402 |
return jobInfoXML; |
293 | 403 |
} |
294 | 404 |
|
405 |
/** |
|
406 |
* Get the information for jobs in a group in an xml format. A parameter |
|
407 |
* key/value pair can be provided as well to limit the jobs returned. |
|
408 |
* |
|
409 |
* @param groupName |
|
410 |
* the job group that we are searching for |
|
411 |
* @param paramName |
|
412 |
* the parameter name that we are looking for. this is ignored if |
|
413 |
* null |
|
414 |
* @param paramValue |
|
415 |
* the parameter value that we are looking for. this is ignored |
|
416 |
* if null |
|
417 |
* @return an XML representation of the jobs. |
|
418 |
*/ |
|
295 | 419 |
public String getJobsInfoXML(String groupName, String paramName, String paramValue) throws ServiceException { |
296 | 420 |
String jobInfoXML = ""; |
297 | 421 |
|
... | ... | |
319 | 443 |
return jobInfoXML; |
320 | 444 |
} |
321 | 445 |
|
446 |
/** |
|
447 |
* Convert a single job to XML |
|
448 |
* @param scheduledJobDAO the job we want to convert |
|
449 |
* @return an XML representation of the job |
|
450 |
*/ |
|
322 | 451 |
public String jobToXML(ScheduledJobDAO scheduledJobDAO) throws ServiceException { |
323 | 452 |
String jobXML = ""; |
324 | 453 |
|
... | ... | |
361 | 490 |
return jobXML; |
362 | 491 |
} |
363 | 492 |
|
364 |
|
|
493 |
/** |
|
494 |
* Start a job in the scheduler |
|
495 |
* |
|
496 |
* @param jobName |
|
497 |
* the name of the job |
|
498 |
* @param startCal |
|
499 |
* a calendar holding the start date of the job |
|
500 |
* @param intervalValue |
|
501 |
* the run interval for the job |
|
502 |
* @param intervalUnit |
|
503 |
* the unit of the run interval for the job |
|
504 |
* @param jobClassName |
|
505 |
* the job class name |
|
506 |
* @param jobGroup |
|
507 |
* the job group name |
|
508 |
* @param jobParams |
|
509 |
* a map of additional job parameters |
|
510 |
* @param username |
|
511 |
* the user name |
|
512 |
* @param groups |
|
513 |
* the user's group name |
|
514 |
*/ |
|
365 | 515 |
private void startJob(String jobName, Calendar startCal, int intervalValue, String intervalUnit, |
366 | 516 |
Class<Job> jobClass, String jobGroup, HashMap<String, String> jobParams) throws ServiceException { |
367 | 517 |
|
... | ... | |
370 | 520 |
|
371 | 521 |
char intervalChar = intervalUnit.charAt(0); |
372 | 522 |
|
523 |
// call the appropriate scheduling method depending on the schedule interval unit |
|
373 | 524 |
switch (intervalChar) { |
374 | 525 |
case 's': |
375 | 526 |
case 'S': |
... | ... | |
393 | 544 |
} |
394 | 545 |
} |
395 | 546 |
|
547 |
/** |
|
548 |
* Schedule a job in the scheduler that has an interval based in seconds |
|
549 |
* |
|
550 |
* @param jobName |
|
551 |
* the name of the job |
|
552 |
* @param jobClass |
|
553 |
* the job class object |
|
554 |
* @param startTime |
|
555 |
* the time of the first run |
|
556 |
* @param interval |
|
557 |
* the interval in seconds between runs |
|
558 |
* @param jobGroup |
|
559 |
* the group of this job |
|
560 |
* @param jobDetail |
|
561 |
* the job detail object |
|
562 |
*/ |
|
396 | 563 |
private void scheduleSecondlyJob(String jobName, Class<Job> jobClass, Calendar startTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException { |
397 | 564 |
|
398 | 565 |
Trigger trigger = TriggerUtils.makeSecondlyTrigger(interval); |
... | ... | |
407 | 574 |
} |
408 | 575 |
} |
409 | 576 |
|
577 |
/** |
|
578 |
* Schedule a job in the scheduler that has an interval based in minutes |
|
579 |
* |
|
580 |
* @param jobName |
|
581 |
* the name of the job |
|
582 |
* @param jobClass |
|
583 |
* the job class object |
|
584 |
* @param startTime |
|
585 |
* the time of the first run |
|
586 |
* @param interval |
|
587 |
* the interval in minutes between runs |
|
588 |
* @param jobGroup |
|
589 |
* the group of this job |
|
590 |
* @param jobDetail |
|
591 |
* the job detail object |
|
592 |
*/ |
|
410 | 593 |
private void scheduleMinutelyJob(String jobName, Class<Job> jobClass, Calendar startTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException { |
411 | 594 |
|
412 | 595 |
Trigger trigger = TriggerUtils.makeMinutelyTrigger(interval); |
... | ... | |
421 | 604 |
} |
422 | 605 |
} |
423 | 606 |
|
607 |
/** |
|
608 |
* Schedule a job in the scheduler that has an interval based in hours |
|
609 |
* |
|
610 |
* @param jobName |
|
611 |
* the name of the job |
|
612 |
* @param jobClass |
|
613 |
* the job class object |
|
614 |
* @param startTime |
|
615 |
* the time of the first run |
|
616 |
* @param interval |
|
617 |
* the interval in hours between runs |
|
618 |
* @param jobGroup |
|
619 |
* the group of this job |
|
620 |
* @param jobDetail |
|
621 |
* the job detail object |
|
622 |
*/ |
|
424 | 623 |
private void scheduleHourlyJob(String jobName, Class<Job> jobClass, Calendar startTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException { |
425 | 624 |
|
426 | 625 |
Trigger trigger = TriggerUtils.makeHourlyTrigger(interval); |
... | ... | |
435 | 634 |
} |
436 | 635 |
} |
437 | 636 |
|
637 |
/** |
|
638 |
* Schedule a job in the scheduler that has an interval based in days |
|
639 |
* |
|
640 |
* @param jobName |
|
641 |
* the name of the job |
|
642 |
* @param jobClass |
|
643 |
* the job class object |
|
644 |
* @param startTime |
|
645 |
* the time of the first run |
|
646 |
* @param interval |
|
647 |
* the interval in days between runs |
|
648 |
* @param jobGroup |
|
649 |
* the group of this job |
|
650 |
* @param jobDetail |
|
651 |
* the job detail object |
|
652 |
*/ |
|
438 | 653 |
private void scheduleDailyJob(String jobName, Class<Job> jobClass, Calendar startTime, int interval, String jobGroup, JobDetail jobDetail) throws ServiceException { |
439 | 654 |
|
440 | 655 |
Trigger trigger = TriggerUtils.makeHourlyTrigger(interval * 24); |
... | ... | |
449 | 664 |
} |
450 | 665 |
} |
451 | 666 |
|
452 |
|
|
453 |
|
|
667 |
/** |
|
668 |
* Extract the start date from the delay value |
|
669 |
* |
|
670 |
* @param delay |
|
671 |
* a string representing the start delay in <value><unit> |
|
672 |
* notation where value is an integer and unit is one of s,m,h or |
|
673 |
* d |
|
674 |
* @return the calendar object holding the start date |
|
675 |
*/ |
|
454 | 676 |
public Calendar getStartDateFromDelay(String delay) throws ServiceException { |
455 | 677 |
Calendar cal = Calendar.getInstance(); |
456 | 678 |
|
... | ... | |
487 | 709 |
} |
488 | 710 |
|
489 | 711 |
return cal; |
490 |
} |
|
491 |
|
|
492 |
|
|
493 |
|
|
494 |
|
|
495 |
|
|
496 |
|
|
712 |
} |
|
497 | 713 |
} |
src/edu/ucsb/nceas/metacat/scheduler/ScheduledJobParamDAO.java | ||
---|---|---|
1 | 1 |
/** |
2 | 2 |
* '$RCSfile$' |
3 |
* Purpose: A Class that holds the data from the scheduled_task
|
|
3 |
* Purpose: A Class that holds the data from the scheduled_job_params
|
|
4 | 4 |
* table in the database. |
5 | 5 |
* Copyright: 2009 Regents of the University of California and the |
6 | 6 |
* National Center for Ecological Analysis and Synthesis |
... | ... | |
35 | 35 |
private String _key; |
36 | 36 |
private String _value; |
37 | 37 |
|
38 |
// get parent job id |
|
38 | 39 |
public Long getJobId() { |
39 | 40 |
return _jobId; |
40 | 41 |
} |
41 | 42 |
|
43 |
// set parent job id |
|
42 | 44 |
public void setJobId(Long jobId) { |
43 | 45 |
_jobId = jobId; |
44 | 46 |
} |
45 | 47 |
|
48 |
// get parameter key |
|
46 | 49 |
public String getKey() { |
47 | 50 |
return _key; |
48 | 51 |
} |
49 | 52 |
|
53 |
// set parameter key |
|
50 | 54 |
public void setKey(String key) { |
51 | 55 |
_key = key; |
52 | 56 |
} |
53 | 57 |
|
58 |
// get parameter value |
|
54 | 59 |
public String getValue() { |
55 | 60 |
return _value; |
56 | 61 |
} |
57 | 62 |
|
63 |
// set parameter value |
|
58 | 64 |
public void setValue(String value) { |
59 | 65 |
_value = value; |
60 | 66 |
} |
src/edu/ucsb/nceas/metacat/scheduler/BaseScheduler.java | ||
---|---|---|
1 | 1 |
/** |
2 | 2 |
* '$RCSfile$' |
3 |
* Purpose: A Class that runs a single scheduled report task
|
|
3 |
* Purpose: An abstract base class for scheduler classes.
|
|
4 | 4 |
* Copyright: 2009 Regents of the University of California and the |
5 | 5 |
* National Center for Ecological Analysis and Synthesis |
6 | 6 |
* Authors: Michael Daigle |
... | ... | |
33 | 33 |
|
34 | 34 |
public abstract class BaseScheduler { |
35 | 35 |
|
36 |
// Schedule a job by extracting job specific information and registering it with the scheduler |
|
37 |
// service. |
|
36 | 38 |
public abstract void scheduleJob(HttpServletRequest request, HttpServletResponse response, |
37 | 39 |
Hashtable<String, String[]> params, String username, String[] groups) throws MetacatSchedulerException; |
38 | 40 |
|
41 |
// Unschedule a job in the scheduler service. |
|
39 | 42 |
public abstract void unScheduleJob(HttpServletRequest request, HttpServletResponse response, |
40 | 43 |
Hashtable<String, String[]> params, String username, String[] groups) throws MetacatSchedulerException; |
41 | 44 |
|
45 |
// Delete a job in the scheduler service. |
|
42 | 46 |
public abstract void deleteJob(HttpServletRequest request, HttpServletResponse response, |
43 | 47 |
Hashtable<String, String[]> params, String username, String[] groups) throws MetacatSchedulerException; |
44 | 48 |
|
49 |
// get all jobs frpm the scheduler service for a specific type of scheduler. |
|
45 | 50 |
public abstract void getJobs(HttpServletRequest request, HttpServletResponse response, |
46 | 51 |
Hashtable<String, String[]> params, String username, String[] groups) throws MetacatSchedulerException; |
47 | 52 |
} |
src/edu/ucsb/nceas/metacat/scheduler/MetacatSchedulerException.java | ||
---|---|---|
1 | 1 |
/** |
2 | 2 |
* '$RCSfile$' |
3 |
* Purpose: An Exception thrown when an error occurs because an |
|
4 |
* AccessionNumber was invalid or used incorrectly |
|
3 |
* Purpose: An Exception thrown when an error occurs in the metacat scheduling |
|
4 |
* system. Note that this is not called SchedulerException to avoid conflicts |
|
5 |
* with an exception in Quartz with the same name. |
|
5 | 6 |
* Copyright: 2008 Regents of the University of California and the |
6 | 7 |
* National Center for Ecological Analysis and Synthesis |
7 | 8 |
* Authors: Michael Daigle |
src/edu/ucsb/nceas/metacat/scheduler/ScheduledJobAccess.java | ||
---|---|---|
47 | 47 |
|
48 | 48 |
private Logger logMetacat = Logger.getLogger(ScheduledJobAccess.class); |
49 | 49 |
|
50 |
// Constructor |
|
50 | 51 |
public ScheduledJobAccess() throws AccessException { |
51 | 52 |
super("ScheduledJobAccess"); |
52 | 53 |
} |
53 | 54 |
|
55 |
/** |
|
56 |
* Get a job based on it's id |
|
57 |
* |
|
58 |
* @param jobId |
|
59 |
* the id of the job in the database |
|
60 |
* @return the scheduled job data object that represents the desired job |
|
61 |
*/ |
|
54 | 62 |
public ScheduledJobDAO getJob(Long jobId) throws AccessException { |
55 | 63 |
ScheduledJobDAO jobDAO = null; |
56 | 64 |
|
65 |
// first get the job from the db and put it into a DAO |
|
57 | 66 |
PreparedStatement pstmt = null; |
58 | 67 |
try { |
59 | 68 |
String sql = "SELECT * FROM scheduled_job WHERE id = ? AND status != 'deleted'"; |
... | ... | |
85 | 94 |
} |
86 | 95 |
} |
87 | 96 |
|
97 |
// Now get all the job parameters and put those into a list of job parameter |
|
98 |
// DAOs and add that list to the job DAO |
|
88 | 99 |
ScheduledJobParamAccess jobParamAccess = new ScheduledJobParamAccess(); |
89 | 100 |
Vector<ScheduledJobParamDAO> jobParamList = |
90 | 101 |
jobParamAccess.getJobParamsForJobId(jobDAO.getId()); |
... | ... | |
96 | 107 |
return jobDAO; |
97 | 108 |
} |
98 | 109 |
|
110 |
/** |
|
111 |
* Get a job by it's name |
|
112 |
* @param jobName the name of the job to get |
|
113 |
* @return the scheduled job data object that represents the desired job |
|
114 |
*/ |
|
99 | 115 |
public ScheduledJobDAO getJobByName(String jobName) throws AccessException { |
100 | 116 |
ScheduledJobDAO jobDAO = null; |
101 | 117 |
|
118 |
// first get the job from the db and put it into a DAO |
|
102 | 119 |
PreparedStatement pstmt = null; |
103 | 120 |
try { |
104 | 121 |
String sql = "SELECT * FROM scheduled_job WHERE name = ? AND status != 'deleted'"; |
... | ... | |
130 | 147 |
} |
Also available in: Unified diff
Beef up comments