001/* 002 * #%L 003 * Netarchivesuite - harvester 004 * %% 005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023 024package dk.netarkivet.harvester.webinterface; 025 026import java.util.List; 027 028import javax.servlet.jsp.PageContext; 029 030 031import org.slf4j.Logger; 032import org.slf4j.LoggerFactory; 033 034import dk.netarkivet.common.exceptions.ArgumentNotValid; 035import dk.netarkivet.common.exceptions.ForwardedToErrorPage; 036import dk.netarkivet.common.exceptions.IOFailure; 037import dk.netarkivet.common.exceptions.UnknownID; 038import dk.netarkivet.common.utils.I18n; 039import dk.netarkivet.common.webinterface.HTMLUtils; 040import dk.netarkivet.harvester.datamodel.Job; 041import dk.netarkivet.harvester.datamodel.JobDAO; 042import dk.netarkivet.harvester.datamodel.JobStatus; 043import dk.netarkivet.harvester.datamodel.JobStatusInfo; 044import dk.netarkivet.harvester.webinterface.HarvestStatusQuery.UI_FIELD; 045 046 047/** 048 * This page provides support for the HarvestStatus pages of the web interface. 049 */ 050public class HarvestStatus { 051 052 /** The logger to use. */ 053 //protected static final Log log = LogFactory.getLog(HarvestStatus.class.getName()); 054 protected static final Logger log = LoggerFactory.getLogger(HarvestStatus.class); 055 056 /** The total number in the full resultset. */ 057 private final long fullResultsCount; 058 059 /** The list of jobs in this HarvestStatus object. */ 060 private final List<JobStatusInfo> jobs; 061 062 /** 063 * Constructor for the HarvestStatus class. 064 * 065 * @param fullResultsCount The total number of entries in the full resultset 066 * @param jobs The list of jobs 067 */ 068 public HarvestStatus(long fullResultsCount, List<JobStatusInfo> jobs) { 069 this.fullResultsCount = fullResultsCount; 070 this.jobs = jobs; 071 } 072 073 /** 074 * @return The total number in the full resultset 075 */ 076 public long getFullResultsCount() { 077 return fullResultsCount; 078 } 079 080 /** 081 * @return The list of jobs in this HarvestStatus object. 082 */ 083 public List<JobStatusInfo> getJobStatusInfo() { 084 return jobs; 085 } 086 087 /** 088 * Process a request from Harveststatus-alljobs. 089 * <p> 090 * Will resubmit a job if requested, otherwise do nothing. 091 * 092 * @param context The web context used for processing 093 * @param i18n The resource i18n context. 094 * @throws ForwardedToErrorPage If an error occurs that stops processing and forwards the user to an error page. 095 */ 096 public static void processRequest(PageContext context, I18n i18n) throws ForwardedToErrorPage { 097 ArgumentNotValid.checkNotNull(context, "PageContext context"); 098 ArgumentNotValid.checkNotNull(i18n, "I18n i18n"); 099 100 // Check if it's a multiple resubmit query 101 String resubmitJobIds = UI_FIELD.RESUBMIT_JOB_IDS.getValue(context.getRequest()); 102 Long resubmitJobID = HTMLUtils.parseOptionalLong(context, Constants.JOB_RESUBMIT_PARAM, null); 103 Long rejectJobID = HTMLUtils.parseOptionalLong(context, Constants.JOB_REJECT_PARAM, null); 104 Long unrejectJobID = HTMLUtils.parseOptionalLong(context, Constants.JOB_UNREJECT_PARAM, null); 105 if (!resubmitJobIds.isEmpty()) { 106 String[] ids = resubmitJobIds.split(";"); 107 for (String idStr : ids) { 108 resubmitJob(context, i18n, Long.parseLong(idStr)); 109 } 110 } else if (resubmitJobID != null) { 111 resubmitJob(context, i18n, resubmitJobID); 112 } else if (rejectJobID != null) { 113 rejectFailedJob(context, i18n, rejectJobID); 114 } else if (unrejectJobID != null) { 115 unrejectRejectedJob(context, i18n, unrejectJobID); 116 } 117 } 118 119 /** 120 * Marks a failed job as rejected for resubmission. Throws a ForwardedToErrorPage if jobID is null or if it refers 121 * to a job that is not in the state FAILED to start with. 122 * 123 * @param context the context for forwarding errors 124 * @param i18n the internationalisation to use 125 * @param jobID the job to reject 126 */ 127 public static void rejectFailedJob(PageContext context, I18n i18n, Long jobID) { 128 try { 129 Job job = JobDAO.getInstance().read(jobID); 130 if (!job.getStatus().equals(JobStatus.FAILED)) { 131 HTMLUtils.forwardWithErrorMessage(context, i18n, "errormsg;job.unable.to.reject", jobID); 132 throw new ForwardedToErrorPage("Cannot reject job in status " + job.getStatus()); 133 } 134 job.setStatus(JobStatus.FAILED_REJECTED); 135 JobDAO.getInstance().update(job); 136 } catch (ArgumentNotValid argumentNotValid) { 137 HTMLUtils.forwardOnEmptyParameter(context, "jobID"); 138 throw new ForwardedToErrorPage("jobID parameter is null"); 139 } catch (UnknownID unknownID) { 140 HTMLUtils.forwardWithErrorMessage(context, i18n, "errormsg;job.unknown.id.0", jobID); 141 throw new ForwardedToErrorPage("Job " + jobID + " not found"); 142 } catch (IOFailure ioFailure) { 143 HTMLUtils.forwardWithErrorMessage(context, i18n, ioFailure, "errormsg;job.unable.to.reject", jobID); 144 throw new ForwardedToErrorPage("Error resubmitting job " + jobID); 145 } 146 147 } 148 149 /** 150 * Marks as failed. Throws a ForwardedToErrorPage if the job is not in the state FAILED_REJECTED to start with. 151 * 152 * @param context the context for forwarding errors 153 * @param i18n the internationalisation to use 154 * @param jobID the job to unreject 155 */ 156 public static void unrejectRejectedJob(PageContext context, I18n i18n, Long jobID) { 157 try { 158 Job job = JobDAO.getInstance().read(jobID); 159 if (!job.getStatus().equals(JobStatus.FAILED_REJECTED)) { 160 HTMLUtils.forwardWithErrorMessage(context, i18n, "errormsg;job.unable.to.reject", jobID); 161 throw new ForwardedToErrorPage("Cannot unreject job in status " + job.getStatus()); 162 } 163 job.setStatus(JobStatus.FAILED); 164 JobDAO.getInstance().update(job); 165 } catch (ArgumentNotValid argumentNotValid) { 166 HTMLUtils.forwardOnEmptyParameter(context, "jobID"); 167 throw new ForwardedToErrorPage("jobID parameter is null"); 168 } catch (UnknownID unknownID) { 169 HTMLUtils.forwardWithErrorMessage(context, i18n, "errormsg;job.unknown.id.0", jobID); 170 throw new ForwardedToErrorPage("Job " + jobID + " not found"); 171 } catch (IOFailure ioFailure) { 172 HTMLUtils.forwardWithErrorMessage(context, i18n, ioFailure, "errormsg;job.unable.to.reject", jobID); 173 throw new ForwardedToErrorPage("Error resubmitting job " + jobID); 174 } 175 } 176 177 /** 178 * Helpermethod to resubmit a job with a given jobID. 179 * 180 * @param context the current pageContext (used in error-handling only) 181 * @param i18n the given internalisation object. 182 * @param jobID The ID for the job that we want to resubmit. 183 */ 184 private static void resubmitJob(PageContext context, I18n i18n, Long jobID) { 185 try { 186 JobDAO.getInstance().rescheduleJob(jobID); 187 } catch (UnknownID e) { 188 HTMLUtils.forwardWithErrorMessage(context, i18n, "errormsg;job.unknown.id.0", jobID); 189 throw new ForwardedToErrorPage("Job " + jobID + " not found"); 190 } catch (IOFailure e) { 191 HTMLUtils.forwardWithErrorMessage(context, i18n, e, "errormsg;job.unable.to.resubmit.id.0", jobID); 192 throw new ForwardedToErrorPage("Error resubmitting job " + jobID); 193 } 194 } 195 196 /** 197 * Create a link to the harvest-run page for a given run. 198 * 199 * @param harvestID The ID of the harvest 200 * @param harvestRun The run # of the harvest (always 0 for snapshots) 201 * @return A properly encoded HTML string with a link and the harvest run as the text. Select all jobs to be shown. 202 */ 203 public static String makeHarvestRunLink(long harvestID, int harvestRun) { 204 ArgumentNotValid.checkNotNegative(harvestID, "harvestID"); 205 ArgumentNotValid.checkNotNegative(harvestRun, "harvestRun"); 206 return "<a href=\"/History/Harveststatus-perharvestrun.jsp?" + HarvestStatusQuery.UI_FIELD.HARVEST_ID.name() 207 + "=" + harvestID + "&" + Constants.HARVEST_NUM_PARAM + "=" + harvestRun + "&" 208 + HarvestStatusQuery.UI_FIELD.JOB_STATUS.name() + "=" + HarvestStatusQuery.JOBSTATUS_ALL + "\">" 209 + harvestRun + "</a>"; 210 } 211 212 /** 213 * Calculate list of job information to be shown. 214 * 215 * @param query the query with its filters. 216 * @return a list of job status info objects 217 */ 218 public static HarvestStatus getjobStatusList(HarvestStatusQuery query) { 219 log.debug("Getting a jobstatuslist based on the current query. "); 220 return JobDAO.getInstance().getStatusInfo(query); 221 } 222 223 /** 224 * Check if next link is active. 225 * 226 * @param pageSize the size of the page 227 * @param totalResultsCount the number of results. 228 * @param endIndex the index of the last result shown on this page 229 * @return true, if link to next page is active 230 */ 231 public static boolean isNextLinkActive(long pageSize, long totalResultsCount, long endIndex) { 232 if (pageSize != 0 && totalResultsCount > 0 && endIndex < totalResultsCount) { 233 return true; 234 } 235 return false; 236 } 237 238 /** 239 * Check if previous link is active. 240 * 241 * @param pageSize the size of the page 242 * @param totalResultsCount the number of results. 243 * @param startIndex the index of the first result shown on this page 244 * @return true, if link to previous page is active 245 */ 246 public static boolean isPreviousLinkActive(long pageSize, long totalResultsCount, long startIndex) { 247 if (pageSize != 0 && totalResultsCount > 0 && startIndex > 1) { 248 return true; 249 } 250 return false; 251 } 252}