1   package com.trendmicro.grid.acl.l0;
2   
3   import com.trendmicro.grid.acl.ProcessingContext;
4   import com.trendmicro.grid.acl.RequiredRoles;
5   import com.trendmicro.grid.acl.Service;
6   import com.trendmicro.grid.acl.l0.datatypes.*;
7   import com.trendmicro.grid.acl.metadata.Metadata;
8   
9   import javax.jws.WebMethod;
10  import javax.jws.WebParam;
11  import javax.jws.WebResult;
12  import javax.jws.WebService;
13  import javax.servlet.annotation.WebServlet;
14  import javax.xml.ws.ResponseWrapper;
15  import java.net.URI;
16  import java.net.URL;
17  import java.util.Collection;
18  import java.util.Date;
19  import java.util.List;
20  import java.util.UUID;
21  
22  import static com.trendmicro.grid.acl.l0.KnownRoles.*;
23  
24  /**
25   * Defines TM reachable services to control the processing inside the GRID.
26   *
27   * @author Juergen_Kellerer, 2010-04-23
28   * @version 1.0
29   */
30  @ProcessingContext
31  @WebServlet("/ws/level-0/internal/processing")
32  @WebService(targetNamespace = Level0Constants.NAMESPACE)
33  public interface ProcessingService extends Service {
34  
35  	/**
36  	 * Prepares a new processing job and returns the job's GUID.
37  	 *
38  	 * @return The GUID of the job.
39  	 * @throws AuthenticationException In case of the current user is not
40  	 *                                 authenticated or doesn't have the right to access the service.
41  	 */
42  	@WebMethod
43  	@WebResult(name = "jobGUID")
44  	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
45  	UUID prepareJob() throws AuthenticationException;
46  
47  	/**
48  	 * Prepares a new processing job and returns the job's GUID.
49  	 *
50  	 * @param parentJobId the GUID of the parent job.
51  	 * @return The GUID of the job.
52  	 * @throws AuthenticationException In case of the current user is not
53  	 *                                 authenticated or doesn't have the right to access the service.
54  	 */
55  	@WebMethod
56  	@WebResult(name = "jobGUID")
57  	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
58  	UUID prepareSubJob(
59  			@WebParam(name = "parentJobGUID") UUID parentJobId) throws AuthenticationException;
60  
61  	/**
62  	 * Cancells the given job if it is still in prepared state.
63  	 *
64  	 * @param jobId The id of the job to cancel.
65  	 * @throws AuthenticationException In case of the current user is not
66  	 *                                 authenticated or doesn't have the right to access the service.
67  	 * @throws IllegalRequestException In case of the job ID is invalid or the job is not in prepared state.
68  	 */
69  	@WebMethod
70  	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
71  	void cancelPerparedJob(
72  			@WebParam(name = "jobGUID") UUID jobId) throws AuthenticationException, IllegalRequestException;
73  
74  	/**
75  	 * Sets the priority of a prepared job.
76  	 *
77  	 * @param jobId       The id of the job to modify.
78  	 * @param jobPriority the priority of the job as an integer value between 1 <= x <= 7.
79  	 *                    1 is the lowest priority, 7 the highest and 4 is the default value.
80  	 * @throws AuthenticationException In case of the current user is not
81  	 *                                 authenticated or doesn't have the right to access the service.
82  	 * @throws IllegalRequestException In case of the job is not in prepared state.
83  	 */
84  	@WebMethod
85  	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
86  	void setJobPriority(
87  			@WebParam(name = "jobGUID") UUID jobId,
88  			@WebParam(name = "jobPriority") int jobPriority) throws AuthenticationException, IllegalRequestException;
89  
90  	/**
91  	 * Starts a prepared processing job after preparation was finished.
92  	 * <p/>
93  	 * Note: Jobs are started when sources were assigned and when the source information
94  	 * contains any changes when compared to the information that exists inside the GRID.
95  	 *
96  	 * @param jobId The id of the job to start.
97  	 * @throws AuthenticationException In case of the current user is not
98  	 *                                 authenticated or doesn't have the right to access the service.
99  	 * @throws IllegalRequestException In case of the job ID is invalid or the job has no assigned sources.
100 	 */
101 	@WebMethod
102 	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
103 	void startJob(@WebParam(name = "jobGUID") UUID jobId) throws AuthenticationException, IllegalRequestException;
104 
105 	/**
106 	 * Starts a prepared processing job after preparation was finished.
107 	 * <p/>
108 	 * This method enforces starting the job even if the information in the GRID appears
109 	 * to be the same.
110 	 *
111 	 * @param jobId The id of the job to start.
112 	 * @throws AuthenticationException In case of the current user is not
113 	 *                                 authenticated or doesn't have the right to access the service.
114 	 * @throws IllegalRequestException In case of the job ID is invalid or the job has no assigned sources.
115 	 */
116 	@WebMethod
117 	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
118 	void enforceStartJob(@WebParam(name = "jobGUID") UUID jobId)
119 			throws AuthenticationException, IllegalRequestException;
120 
121 	/**
122 	 * Initiates a reprocessing job on the given file and returns the job GUID for monitoring the progress.
123 	 * <p/>
124 	 * Note: This method is similar to running the code below, with the major difference that the
125 	 * operation is <b>atomic</b> and <b>transaction safe</b>:<pre><code>
126 	 * UUID jobId = prepareJob();
127 	 * <p/>
128 	 * SourceIdentiferListPage sourceIds = sourceService.getReferencingSources(fileId, 0);
129 	 * SourceIdentifier sid = sourceIds.getElements().get(0);
130 	 * Source source = sourceService.getSource(sid);
131 	 * SourceInformation info = source.getSourceInformation();
132 	 * <p/>
133 	 * sid = assignProcessSource(jobId, source.getRemoteURI(),
134 	 *         info.getLastModified(), info.getContentTag(), source.getMetadata());
135 	 * assignExistingContentToProcessSource(sid, fileId);
136 	 * <p/>
137 	 * enforceStartJob(jobId);
138 	 * </code></pre>
139 	 *
140 	 * @param contentIdentifier        The identifier of a previously stored file content.
141 	 * @param assignAllExistingSources Whether the newly created job will get the most recent
142 	 *                                 or all stored sources assigned.
143 	 * @param jobPriority              the priority of the job as an integer value between 1 <= x <= 7.
144 	 *                                 1 is the lowest priority, 7 the highest and 4 is the default value.
145 	 * @return The GUID of the job.
146 	 * @throws AuthenticationException In case of the current user is not
147 	 *                                 authenticated or doesn't have the right to access the service.
148 	 * @throws IllegalRequestException If the content identifier does not point to an existing file content
149 	 *                                 or when no public source URIs were assigned to the file.
150 	 */
151 	@WebMethod
152 	@WebResult(name = "jobGUID")
153 	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
154 	UUID startReprocessingJob(
155 			@WebParam(name = "contentIdentifier") FileIdentifier contentIdentifier,
156 			@WebParam(name = "assignAllExistingSources") boolean assignAllExistingSources,
157 			@WebParam(name = "jobPriority") int jobPriority) throws AuthenticationException, IllegalRequestException;
158 
159 	/**
160 	 * Initiates a reprocessing job on the given file and returns the job GUID for monitoring the progress.
161 	 * <p/>
162 	 * This method is similar to {@link #startReprocessingJob(FileIdentifier, boolean, int)} with the major
163 	 * difference that it allows to explicitly select which of the sources assigned with the package will
164 	 * be used for reprocessing.
165 	 * <p/>
166 	 * Note: Calling this method with a source identifier that has not been assigned to the file
167 	 * will result in throwing an {@code IllegalRequestException}. Only assigned sources are allowed
168 	 * to be used as method parameters.
169 	 *
170 	 * @param contentIdentifier         The identifier of a previously stored file content.
171 	 * @param selectedSourceIdentifiers A list of identifiers to assign with the reprocessing job.
172 	 * @param jobPriority               the priority of the job as an integer value between 1 <= x <= 7.
173 	 *                                  1 is the lowest priority, 7 the highest and 4 is the default value.
174 	 * @return The GUID of the job.
175 	 * @throws AuthenticationException In case of the current user is not
176 	 *                                 authenticated or doesn't have the right to access the service.
177 	 * @throws IllegalRequestException If the content identifier does not point to an existing file content
178 	 *                                 or when no public source URIs were assigned to the file.
179 	 */
180 	@WebMethod
181 	@WebResult(name = "jobGUID")
182 	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
183 	UUID startReprocessingJobWithSources(
184 			@WebParam(name = "contentIdentifier") FileIdentifier contentIdentifier,
185 			@WebParam(name = "sourceIdentifier") Collection<SourceIdentifier> selectedSourceIdentifiers,
186 			@WebParam(name = "jobPriority") int jobPriority) throws AuthenticationException, IllegalRequestException;
187 
188 	/**
189 	 * Clones the given job and starts the clone.
190 	 * <p/>
191 	 * The clone contains the same sources and settings as the original.
192 	 * If the latter if not yet closed, its state will be set to {@link Job.State#ABORTED}, in order to
193 	 * avoid double retrieval of the same processing results.
194 	 * <p/>
195 	 * This method is useful to restart stale jobs (jobs running for a very long time without an update).
196 	 * Note: Closing a job does not abort processing, it only sets the ABORTED flag within the DB. Processing
197 	 * services outside of the ACL need to query this state if they need to act on the event of closing a job.
198 	 * <p/>
199 	 * In case of a job is closed and results still reach the method call
200 	 * {@link #storeProcessingResultsAndFinalizeJobs(java.util.Collection)}, the processing results of the
201 	 * relevant job will get discarded and warning will be logged as indication.
202 	 *
203 	 * @param originalJobId the job to clone and close.
204 	 * @return the UUID of the new, cloned job.
205 	 * @throws AuthenticationException In case of the current user is not
206 	 *                                 authenticated or doesn't have the right to access the service.
207 	 * @throws IllegalRequestException If the jobId does not point to an existing job.
208 	 */
209 	@WebMethod
210 	@WebResult(name = "jobGUID")
211 	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
212 	UUID cloneAndStartJob(@WebParam(name = "originalJobGUID") UUID originalJobId)
213 			throws AuthenticationException, IllegalRequestException;
214 
215 	/**
216 	 * Retrieves all sources that are currently assigned to the given job.
217 	 *
218 	 * @param jobId the id of the job to query.
219 	 * @return all sources that are currently assigned to the given job.
220 	 * @throws AuthenticationException In case of the current user is not
221 	 *                                 authenticated or doesn't have the right to access the service.
222 	 */
223 	@WebMethod
224 	@WebResult(name = "source")
225 	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
226 	List<Source> getAssignedSources(@WebParam(name = "jobGUID") UUID jobId) throws AuthenticationException;
227 
228 	/**
229 	 * Adds or updates the remote source with the given Metadata, assigns it to a single processing
230 	 * job and returns the source identifier which may be used to upload source content if required.
231 	 * <p/>
232 	 * Notes:
233 	 * <ul>
234 	 * <li>This method is intended to provide the required input for adding sources to processing jobs.</li>
235 	 * <li>The internal logic will detect whether the values refer to an existing or new source.</li>
236 	 * <li>This method doesn't immediately update or add the source. Instead the change
237 	 * is kept inside the session and will be applied when a corresponding processing job is started.</li>
238 	 * <li>This method will never create sources with '<code>temporary == true</code>'.</li>
239 	 * </ul>
240 	 *
241 	 * @param jobId           the id of the job to add the source to.
242 	 * @param remoteSourceURI The remote URI of the source.
243 	 * @param lastModified    The remote last modified date of the source, if known (may be set to 'null').
244 	 * @param contentTag      The remote content tag (e.g. ETAG) of the source, if known (may be set to 'null').
245 	 * @param metadata        The metadata to store with the source.
246 	 * @return the identifier of the assigned process source.
247 	 * @throws AuthenticationException In case of the current user is not
248 	 *                                 authenticated or doesn't have the right to access the service.
249 	 * @throws IllegalRequestException In case of the job ID is not pointing to a prepared job or if the source
250 	 *                                 is already assigned to another job in the same session.
251 	 */
252 	@WebMethod
253 	@WebResult(name = "sourceIdentifier")
254 	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
255 	SourceIdentifier assignProcessSource(
256 			@WebParam(name = "jobGUID") UUID jobId,
257 			@WebParam(name = "remoteSourceURL") URI remoteSourceURI,
258 			@WebParam(name = "lastModified") Date lastModified,
259 			@WebParam(name = "contentTag") String contentTag,
260 			@WebParam(name = "metadata") Metadata metadata) throws AuthenticationException, IllegalRequestException;
261 
262 	/**
263 	 * Returns a public reachable transfer URL that may be used to upload (HTTP-PUT) the binary
264 	 * content of the source.
265 	 * <p/>
266 	 * <b>Note:</b> By uploading content to the returned URL via HTTP-PUT, the access layer will set the
267 	 * Meta elements "sourceContentSHA1" and "sourceContentMD5" inside the Metadata section of
268 	 * the assigned Source to the hash values that are automatically calculated on the data stream while
269 	 * uploading.
270 	 *
271 	 * @param sourceIdentifier The identifier of a previously assigned process source.
272 	 * @return a public reachable transfer URL that may be used to upload the
273 	 *         binary content of the source using the method "HTTP PUT".
274 	 * @throws AuthenticationException In case of the current user is not
275 	 *                                 authenticated or doesn't have the right to access the service.
276 	 * @throws IllegalRequestException In case of the source identifier is not referring to a previously
277 	 *                                 assigned process source.
278 	 */
279 	@WebMethod
280 	@WebResult(name = "uploadURL")
281 	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT, ROLE_CREATE_BINARY_CONTENT})
282 	URL assignContentToProcessSource(
283 			@WebParam(name = "sourceIdentifier") SourceIdentifier sourceIdentifier)
284 			throws AuthenticationException, IllegalRequestException;
285 
286 	/**
287 	 * Allows to assign content that is known to exist already inside the GRID avoiding any new uploads.
288 	 * <p/>
289 	 * <b>Note:</b> The implementation behind this method checks that the source is a previously
290 	 * assigned process source, and that the contentIdentifier is referring to a file that is
291 	 * contained inside the file content repository.
292 	 *
293 	 * @param sourceIdentifier  The identifier of a previously assigned process source.
294 	 * @param contentIdentifier The identifier of a previously stored file content.
295 	 * @throws AuthenticationException In case of the current user is not
296 	 *                                 authenticated or doesn't have the right to access the service.
297 	 * @throws IllegalRequestException In case of the source identifier is not referring to a previously
298 	 *                                 assigned process source OR in case of the file identifier doesn't
299 	 *                                 refer to a file stored inside the file content repository.
300 	 */
301 	@WebMethod
302 	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
303 	void assignExistingContentToProcessSource(
304 			@WebParam(name = "sourceIdentifier") SourceIdentifier sourceIdentifier,
305 			@WebParam(name = "contentIdentifier") FileIdentifier contentIdentifier)
306 			throws AuthenticationException, IllegalRequestException;
307 
308 	/**
309 	 * Adds or updates the remote source with the given Metadata, assigns it to a single processing
310 	 * job and directly returns an upload URL if GRID does not yet know the content.
311 	 * <p/>
312 	 * This method is a convenience implementation that reduces the amount of API calls required to perform the default
313 	 * harvesting task, thus the following 2 code snippets lead to exactly the same results:<code><pre>
314 	 * SourceIdentifier sourceIdentifier = assignProcessSource(jobId, remoteSourceURI, lastModified, contentTag, metadata);
315 	 * boolean contentMayBeMissing = true;
316 	 * Source source = sourceService.getSource(sourceIdentifier);
317 	 * if (source != null) {
318 	 *     FileIdentifier existingIdentifier = source.getSourceContentIdentifier();
319 	 *     if (existingIdentifier != null) {
320 	 *         contentMayBeMissing = !existingIdentifier.equals(contentIdentifier);
321 	 *     }
322 	 * }
323 	 * URL putURL = null;
324 	 * if (contentMayBeMissing) {
325 	 *     try {
326 	 *         assignExistingContentToProcessSource(sourceIdentifier, contentIdentifier);
327 	 *     } catch (IllegalRequestException ignored) {
328 	 *         putURL = assignContentToProcessSource(sourceIdentifier);
329 	 *     }
330 	 * }
331 	 * if (putURL != null) {
332 	 *     //TODO: Do the upload
333 	 * }
334 	 * </pre></code> can be <b>replaced with</b>: <code><pre>
335 	 * URL putURL = assignProcessSourceWithContent(jobId, contentIdentifier, remoteSourceURI, lastModified, contentTag, metadata);
336 	 * if (putURL != null) {
337 	 *     //TODO: Do the upload
338 	 * }
339 	 * </pre></code>
340 	 *
341 	 * @param jobId             the id of the job to add the source to.
342 	 * @param remoteSourceURI   The remote URI of the source.
343 	 * @param lastModified      The remote last modified date of the source, if known (may be set to 'null').
344 	 * @param contentTag        The remote content tag (e.g. ETAG) of the source, if known (may be set to 'null').
345 	 * @param metadata          The metadata to store with the source.
346 	 * @param contentIdentifier The identifier of a previously stored file content.
347 	 * @return 'null' if the content is already known by GRID and does not require to get uploaded OR
348 	 *         a public reachable transfer URL that may be used to upload the binary content of the source using the method "HTTP PUT".
349 	 * @throws AuthenticationException In case of the current user is not
350 	 *                                 authenticated or doesn't have the right to access the service.
351 	 * @throws IllegalRequestException In case of the job ID is not pointing to a prepared job or if the source
352 	 *                                 is already assigned to another job in the same session.
353 	 */
354 	@WebMethod
355 	@WebResult(name = "uploadURL")
356 	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT, ROLE_CREATE_BINARY_CONTENT})
357 	URL assignProcessSourceWithContent(@WebParam(name = "jobGUID") UUID jobId,
358 	                                   @WebParam(name = "contentIdentifier") FileIdentifier contentIdentifier,
359 	                                   @WebParam(name = "remoteSourceURL") URI remoteSourceURI,
360 	                                   @WebParam(name = "lastModified") Date lastModified,
361 	                                   @WebParam(name = "contentTag") String contentTag,
362 	                                   @WebParam(name = "metadata") Metadata metadata)
363 			throws AuthenticationException, IllegalRequestException;
364 
365 	/**
366 	 * Receives a collection of final processing results, stores them inside the GRID CoreDB and
367 	 * performs the final update on the assigned jobs.
368 	 *
369 	 * @param processingResults the processing results to update.
370 	 * @throws AuthenticationException In case of the current user is not
371 	 *                                 authenticated or doesn't have the right to access the service.
372 	 * @throws StorageFailedException  In case of the storage failed on one of the data sets.
373 	 */
374 	@WebMethod
375 	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
376 	void storeProcessingResultsAndFinalizeJobs(
377 			@WebParam(name = "processingResult") Collection<ProcessPackageDataSet> processingResults)
378 			throws AuthenticationException, StorageFailedException;
379 
380 	/**
381 	 * Returns a paged list of running jobs.
382 	 *
383 	 * @param pageNumber The page number of the list page to return (0 is first page).
384 	 * @return A single list page for the given page number or 'null' if no jobs are running or the
385 	 *         pageNumber is out of range.
386 	 * @throws AuthenticationException In case of the current user is not
387 	 *                                 authenticated or doesn't have the right to access the service.
388 	 */
389 	@WebMethod
390 	@WebResult(name = "runningJobs")
391 	@RequiredRoles(ROLE_ACCESS_PROTECTED_SERVICES)
392 	UUIDListPage getRunningJobs(
393 			@WebParam(name = "pageNumber") int pageNumber) throws AuthenticationException;
394 
395 	/**
396 	 * Returns a paged list of jobs that are in the given state.
397 	 *
398 	 * @param pageNumber The page number of the list page to return (0 is first page).
399 	 * @param jobState   The state of the jobs to query.
400 	 * @return A single list page for the given page number or 'null' if no jobs are running or the
401 	 *         pageNumber is out of range.
402 	 * @throws AuthenticationException In case of the current user is not
403 	 *                                 authenticated or doesn't have the right to access the service.
404 	 */
405 	@WebMethod
406 	@WebResult(name = "jobGUIDs")
407 	@RequiredRoles(ROLE_ACCESS_PROTECTED_SERVICES)
408 	UUIDListPage getJobsInState(
409 			@WebParam(name = "jobState") Job.State jobState,
410 			@WebParam(name = "pageNumber") int pageNumber) throws AuthenticationException;
411 
412 	/**
413 	 * Returns a paged list of jobs that are in the given state and were last updated within the given range.
414 	 *
415 	 * @param pageNumber       The page number of the list page to return (0 is first page).
416 	 * @param jobState         The state of the jobs to query.
417 	 * @param lastUpdatedRange The range when the last update was recorded.
418 	 * @return A single list page for the given page number or 'null' if no jobs are running or the
419 	 *         pageNumber is out of range.
420 	 * @throws AuthenticationException In case of the current user is not
421 	 *                                 authenticated or doesn't have the right to access the service.
422 	 */
423 	@WebMethod
424 	@WebResult(name = "jobGUIDs")
425 	@RequiredRoles(ROLE_ACCESS_PROTECTED_SERVICES)
426 	UUIDListPage getJobsInStateAndRange(
427 			@WebParam(name = "jobState") Job.State jobState,
428 			@WebParam(name = "lastUpdatedRange") DaysRange lastUpdatedRange,
429 			@WebParam(name = "pageNumber") int pageNumber) throws AuthenticationException;
430 
431 	/**
432 	 * Returns the states of the jobs, identified by their ids.
433 	 *
434 	 * @param jobIds The GUIDs of the jobs to return.
435 	 * @return the jobs, identified by their ids.
436 	 * @throws AuthenticationException In case of the current user is not
437 	 *                                 authenticated or doesn't have the right to access the service.
438 	 */
439 	@WebMethod
440 	@WebResult(name = "jobState")
441 	@ResponseWrapper( // Adding a custom response wrapper to support 'null' values inside the returned collection.
442 			className = "com.trendmicro.grid.acl.l0.wrappers.GetJobStatesResponse")
443 	@RequiredRoles(ROLE_ACCESS_PROTECTED_SERVICES)
444 	Collection<Job.State> getJobStates(
445 			@WebParam(name = "jobGUID") Collection<UUID> jobIds) throws AuthenticationException;
446 
447 	/**
448 	 * Returns the read & writable information on a job, identified by its id.
449 	 *
450 	 * @param job The GUID of the job to return the details from.
451 	 * @return the details on a job, identified by its id.
452 	 * @throws AuthenticationException In case of the current user is not
453 	 *                                 authenticated or doesn't have the right to access the service.
454 	 */
455 	@WebMethod
456 	@WebResult(name = "job")
457 	@RequiredRoles(ROLE_ACCESS_PROTECTED_SERVICES)
458 	Job getJob(
459 			@WebParam(name = "jobGUID") UUID job) throws AuthenticationException;
460 
461 	/**
462 	 * Returns the read & writable information on the jobs, identified by their ids.
463 	 *
464 	 * @param jobIds The GUIDs of the jobs to return.
465 	 * @return the jobs, identified by their ids.
466 	 * @throws AuthenticationException In case of the current user is not
467 	 *                                 authenticated or doesn't have the right to access the service.
468 	 */
469 	@WebMethod
470 	@WebResult(name = "job")
471 	@ResponseWrapper( // Adding a custom response wrapper to support 'null' values inside the returned collection.
472 			className = "com.trendmicro.grid.acl.l0.wrappers.GetJobsResponse")
473 	@RequiredRoles(ROLE_ACCESS_PROTECTED_SERVICES)
474 	Collection<Job> getJobs(
475 			@WebParam(name = "jobGUID") Collection<UUID> jobIds) throws AuthenticationException;
476 
477 	/**
478 	 * Updates the given job inside the persistent store (= the database)
479 	 *
480 	 * @param job the details to update.
481 	 * @throws AuthenticationException In case of the current user is not
482 	 *                                 authenticated or doesn't have the right to access the service.
483 	 * @throws IllegalRequestException In case of the values were changed to invalid settings.
484 	 */
485 	@WebMethod
486 	@RequiredRoles({ROLE_ACCESS_PROTECTED_SERVICES, ROLE_PROCESS_CONTENT})
487 	void updateJob(
488 			@WebParam(name = "job") Job job) throws AuthenticationException, IllegalRequestException;
489 
490 	/**
491 	 * Returns the detailed information on a job, identified by its id.
492 	 *
493 	 * @param job The GUID of the job to return the details for.
494 	 * @return the details on a job, identified by its id.
495 	 * @throws AuthenticationException In case of the current user is not
496 	 *                                 authenticated or doesn't have the right to access the service.
497 	 */
498 	@WebMethod
499 	@WebResult(name = "job")
500 	@RequiredRoles(ROLE_ACCESS_PROTECTED_SERVICES)
501 	JobDetails getJobDetails(
502 			@WebParam(name = "jobGUID") UUID job) throws AuthenticationException;
503 }