/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE file at the root of the source * tree and available online at * * https://github.com/keeps/roda */ package org.roda.wui.api.controllers; import java.util.Arrays; import java.util.List; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.roda.core.RodaCoreFactory; import org.roda.core.data.common.RodaConstants; import org.roda.core.data.exceptions.AuthorizationDeniedException; import org.roda.core.data.exceptions.GenericException; import org.roda.core.data.exceptions.InvalidParameterException; import org.roda.core.data.exceptions.JobAlreadyStartedException; import org.roda.core.data.exceptions.NotFoundException; import org.roda.core.data.exceptions.RequestNotValidException; import org.roda.core.data.v2.IsRODAObject; import org.roda.core.data.v2.common.Pair; import org.roda.core.data.v2.index.IndexResult; import org.roda.core.data.v2.index.facet.Facets; import org.roda.core.data.v2.index.filter.Filter; import org.roda.core.data.v2.index.filter.SimpleFilterParameter; import org.roda.core.data.v2.index.select.SelectedItemsNone; import org.roda.core.data.v2.index.sort.Sorter; import org.roda.core.data.v2.index.sublist.Sublist; import org.roda.core.data.v2.jobs.IndexedReport; import org.roda.core.data.v2.jobs.Job; import org.roda.core.data.v2.jobs.Report.PluginState; import org.roda.core.data.v2.jobs.Reports; import org.roda.core.data.v2.user.User; import org.roda.core.index.IndexService; import org.roda.core.model.ModelService; import org.roda.core.plugins.Plugin; import org.roda.core.util.IdUtils; import org.roda.wui.api.v1.utils.ApiUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JobsHelper { private static final Logger LOGGER = LoggerFactory.getLogger(JobsHelper.class); private JobsHelper() { // do nothing } protected static void validateAndSetJobInformation(User user, Job job) throws RequestNotValidException { LOGGER.debug("Job being validated: {}", job); validateJobPluginInformation(job); // always set a new UUID (even if job already brings one) job.setId(IdUtils.createUUID()); // set "missing" information whenever it is not impeditive for job creation if (StringUtils.isBlank(job.getName())) { job.setName(job.getId()); } job.setUsername(user.getName()); } private static void validateJobPluginInformation(Job job) throws RequestNotValidException { Plugin<? extends IsRODAObject> plugin = RodaCoreFactory.getPluginManager().getPlugin(job.getPlugin()); if (plugin != null) { // validate parameters try { plugin.setParameterValues(job.getPluginParameters()); if (!plugin.areParameterValuesValid()) { throw new RequestNotValidException("Invalid plugin parameters"); } job.setPluginType(plugin.getType()); } catch (InvalidParameterException e) { throw new RequestNotValidException("Invalid plugin parameters"); } validatePluginObjectsClasses(job, plugin); } else { throw new RequestNotValidException("No plugin was found with the id '" + job.getPlugin() + "'"); } } private static void validatePluginObjectsClasses(Job job, Plugin<? extends IsRODAObject> plugin) throws RequestNotValidException { if (!(job.getSourceObjects() instanceof SelectedItemsNone)) { // validate plugin class & objects class Set<?> pluginObjectClasses = RodaCoreFactory.getPluginManager().getPluginObjectClasses(plugin); String objectsClassName = job.getSourceObjects().getSelectedClass(); Class<?> objectsClass; try { objectsClass = Class.forName(objectsClassName); } catch (ClassNotFoundException e) { throw new RequestNotValidException("Plugin class and objects class do not match (plugin classes: " + pluginObjectClasses + "; objects class: " + objectsClassName + ")"); } if (!pluginObjectClasses.contains(objectsClass)) { throw new RequestNotValidException("Plugin class and objects class do not match (plugin classes: " + pluginObjectClasses + "; objects class: " + objectsClass + ")"); } } } protected static Job createJob(Job job, boolean async) throws NotFoundException, GenericException, JobAlreadyStartedException, RequestNotValidException, AuthorizationDeniedException { Job updatedJob = new Job(job); // serialize job to file & index it RodaCoreFactory.getModelService().createJob(updatedJob); // ask plugin orchestrator to execute the job (which will be executed // asynchronously) RodaCoreFactory.getPluginOrchestrator().executeJob(updatedJob, async); // force commit RodaCoreFactory.getIndexService().commit(Job.class); return updatedJob; } public static org.roda.core.data.v2.jobs.Jobs getJobsFromIndexResult(User user, String start, String limit, List<String> fieldsToReturn) throws GenericException, AuthorizationDeniedException, RequestNotValidException { org.roda.core.data.v2.jobs.Jobs jobs = new org.roda.core.data.v2.jobs.Jobs(); Pair<Integer, Integer> pagingParams = ApiUtils.processPagingParams(start, limit); boolean justActive = false; IndexResult<Job> listJobsIndexResult = org.roda.wui.api.controllers.Browser.find(Job.class, Filter.ALL, Sorter.NONE, new Sublist(new Sublist(pagingParams.getFirst(), pagingParams.getSecond())), Facets.NONE, user, justActive, fieldsToReturn); for (Job job : listJobsIndexResult.getResults()) { jobs.addJob(job); } return jobs; } public static Job startJob(String jobId) throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException, JobAlreadyStartedException { // get job Job job = RodaCoreFactory.getModelService().retrieveJob(jobId); // ask plugin orchestrator to execute the job RodaCoreFactory.getPluginOrchestrator().executeJob(job, true); return job; } public static Job stopJob(String jobId) throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException { // retrieve job Job job = RodaCoreFactory.getModelService().retrieveJob(jobId); // stop it RodaCoreFactory.getPluginOrchestrator().stopJob(job); return job; } public static void deleteJob(String jobId) throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException { // stop it (if it is running) Job job = stopJob(jobId); // delete all job reports associated with this job deleteJobReports(job); // delete it RodaCoreFactory.getModelService().deleteJob(jobId); } private static void deleteJobReports(Job job) throws GenericException, RequestNotValidException { Filter filter = new Filter(new SimpleFilterParameter(RodaConstants.JOB_REPORT_JOB_ID, job.getId())); Sublist sublist = new Sublist(0, RodaConstants.DEFAULT_PAGINATION_VALUE); ModelService model = RodaCoreFactory.getModelService(); IndexService index = RodaCoreFactory.getIndexService(); Long jobReportsCount = index.count(IndexedReport.class, filter); for (int i = 0; i < jobReportsCount; i += RodaConstants.DEFAULT_PAGINATION_VALUE) { sublist.setFirstElementIndex(i); IndexResult<IndexedReport> jobReports = index.find(IndexedReport.class, filter, null, sublist, Arrays.asList(RodaConstants.JOB_REPORT_ID, RodaConstants.JOB_REPORT_JOB_ID)); for (IndexedReport report : jobReports.getResults()) { try { model.deleteJobReport(report.getJobId(), report.getId()); } catch (NotFoundException | AuthorizationDeniedException e) { LOGGER.error("Error while deleting Job Report", e); } } } } public static Reports getJobReportsFromIndexResult(User user, String jobId, boolean justFailed, String start, String limit, List<String> fieldsToReturn) throws GenericException, AuthorizationDeniedException, RequestNotValidException { Reports reports = new Reports(); Pair<Integer, Integer> pagingParams = ApiUtils.processPagingParams(start, limit); boolean justActive = false; Filter filter = new Filter(new SimpleFilterParameter(RodaConstants.JOB_REPORT_JOB_ID, jobId)); if (justFailed) { filter.add(new SimpleFilterParameter(RodaConstants.JOB_REPORT_PLUGIN_STATE, PluginState.FAILURE.toString())); } IndexResult<IndexedReport> listJobReportsIndexResult = org.roda.wui.api.controllers.Browser.find( IndexedReport.class, filter, Sorter.NONE, new Sublist(new Sublist(pagingParams.getFirst(), pagingParams.getSecond())), Facets.NONE, user, justActive, fieldsToReturn); for (IndexedReport report : listJobReportsIndexResult.getResults()) { reports.addObject(report); } return reports; } }