/**
   * Method for adding an entry for administration.
   *
   * @param filename The name of the file to be stored.
   * @param msg The StoreMessage of the entry.
   * @param checksum The checksum of the entry.
   * @throws ArgumentNotValid If either the filename or checksum is either null or the empty string.
   */
  @Override
  public void addEntry(String filename, StoreMessage msg, String checksum) throws ArgumentNotValid {
    ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename");
    ArgumentNotValid.checkNotNullOrEmpty(checksum, "String checksum");

    // insert this into the entries map.
    storeEntries.put(filename, msg);

    // insert into database.
    database.insertNewFileForUpload(filename, checksum);
  }
  /**
   * Returns the ReplicaStoreState of a given file in a specific replica.
   *
   * @param filename The name of the file for the ReplicaStoreState.
   * @param replicaChannelName The name of the identification channel for uniquely identifying the
   *     replica of for the ReplicaStoreState.
   * @return The ReplicaStoreState of a given file in a specific replica.
   * @throws ArgumentNotValid If the filename or the replica id is null or the empty string.
   */
  @Override
  public ReplicaStoreState getState(String filename, String replicaChannelName)
      throws ArgumentNotValid {
    ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename");
    ArgumentNotValid.checkNotNullOrEmpty(replicaChannelName, "String replicaChannelName");

    Replica rep = Channels.retrieveReplicaFromIdentifierChannel(replicaChannelName);

    // retrieve the ReplicaStoreState from the database.
    return database.getReplicaStoreState(filename, rep.getId());
  }
  /**
   * Sets the checksum of a given file.
   *
   * <p>It should not be possible to change the checksum in the database through arcrepository.
   *
   * @param filename The name of the file to have the checksum changed.
   * @param checksum The new checksum for the file.
   * @throws ArgumentNotValid If either the filename or the checksum is either null or the empty
   *     string.
   * @throws IllegalState Always, since it is not allowed for arcrepository to change the checksum
   *     of a completed upload.
   */
  @Override
  public void setCheckSum(String filename, String checksum) throws ArgumentNotValid, IllegalState {
    ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename");
    ArgumentNotValid.checkNotNullOrEmpty(checksum, "String checksum");

    // This will not be implemented.
    throw new IllegalState(
        "It is not possible to change the checksum of a "
            + " file in the database! Only the checksum of a specific "
            + "replicafileinfo.");
  }
  /**
   * Message to signal from a BitarchiveServer to the BitarchiveMonitorServer that the Bit Archive
   * Application identified by BA_ApplicationId has completed its part of the batch job.
   *
   * <p>Holds status information: list of files processed and a list of ARC files (file names) on
   * which the batch job failed.
   *
   * @param to the channel to which this message is to be sent (must be a BAMON channel)
   * @param baAppId Identifier for the machine sending this message, usually containing the IP
   *     address and http port number
   * @param originatingBatchMsgId the Id field from the original batch message
   * @param rf he remote file reference containing the output of the batch job (may be null if no
   *     output is generated).
   * @throws ArgumentNotValid If the BA_ApplicationId or the originatingBatchMsgId are null or
   *     empty, or if the channel 'to' is null.
   */
  public BatchEndedMessage(
      ChannelID to, String baAppId, String originatingBatchMsgId, RemoteFile rf)
      throws ArgumentNotValid {
    super(to, Channels.getError());
    ArgumentNotValid.checkNotNull(to, "ChannelID to");
    ArgumentNotValid.checkNotNullOrEmpty(baAppId, "String baAppId");
    ArgumentNotValid.checkNotNullOrEmpty(originatingBatchMsgId, "String originatingBatchMsgId");

    this.baApplicationId = baAppId;
    this.originatingBatchMsgId = originatingBatchMsgId;
    this.rf = rf;
  }
  /**
   * Sets the store state of an entry to a specific value.
   *
   * @param filename The name of the file for the entry.
   * @param repChannelId The identification channel of the replica for the entry.
   * @param state The new state for the entry.
   * @throws ArgumentNotValid If the ReplicaStoreState is null, or if either the filename or the
   *     replica identification channel is either null or the empty string.
   */
  @Override
  public void setState(String filename, String repChannelId, ReplicaStoreState state)
      throws ArgumentNotValid {
    ArgumentNotValid.checkNotNull(state, "ReplicaStoreState state");
    ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename");
    ArgumentNotValid.checkNotNullOrEmpty(repChannelId, "String repChannelId");

    // retrieve the replica
    Replica rep = Channels.retrieveReplicaFromIdentifierChannel(repChannelId);

    // update the database.
    database.setReplicaStoreState(filename, rep.getId(), state);
  }
  /**
   * Determines whether a given file in a specific replica has a valid replica store state. By valid
   * means a replica store state other that UNKNOWN_UPLOAD_STATE.
   *
   * <p>TODO Find out if the assumption that all upload states besides UNKNOWN_UPLOAD_STATE are
   * acceptable!
   *
   * @param filename The name of the file for the ReplicaStoreState.
   * @param repChannelId The identification channel of the replica for the ReplicaStoreState.
   * @return Whether a given file in a specific replica has a valid store state.
   * @throws ArgumentNotValid If either the filenames or the replica identification channel is null
   *     or the empty string.
   */
  @Override
  public boolean hasState(String filename, String repChannelId) throws ArgumentNotValid {
    ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename");
    ArgumentNotValid.checkNotNullOrEmpty(repChannelId, "String repChannelId");

    // retrieve the replica
    Replica rep = Channels.retrieveReplicaFromIdentifierChannel(repChannelId);

    // retrieve the state for the entry for the replica and filename
    ReplicaStoreState state = database.getReplicaStoreState(filename, rep.getId());

    // return whether the entry has a known upload state
    return state != ReplicaStoreState.UNKNOWN_UPLOAD_STATE;
  }
  /**
   * Method for telling whether a file entry exists.
   *
   * @param filename The name of the file, the existence of whose entry is to be determined.
   * @return Whether the entry exists.
   * @throws ArgumentNotValid If the filename is either null or empty.
   */
  @Override
  public boolean hasEntry(String filename) throws ArgumentNotValid {
    ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename");

    // See if the file can be found in the database.
    return database.existsFileInDB(filename);
  }
  /**
   * Retrieves the StoreMessage of a specific file.
   *
   * @param filename The name of the file whose StoreMessage should be retrieved.
   * @return The StoreMessage corresponding to the file. A null is returned if the corresponding
   *     StoreMessage is not found.
   * @throws ArgumentNotValid If the filename is either null or the empty string.
   */
  @Override
  public StoreMessage removeReplyInfo(String filename) throws ArgumentNotValid {
    ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename");

    // extract the entry from the
    return storeEntries.remove(filename);
  }
  /**
   * Determines whether the StoreMessage of a given file exists.
   *
   * @param filename The name of the file to which the existence of the StoreMessage should be
   *     determined.
   * @return Whether the StoreMessage of the file exists.
   * @throws ArgumentNotValid If the filename is null or the empty string.
   */
  @Override
  public boolean hasReplyInfo(String filename) throws ArgumentNotValid {
    ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename");

    // check if a entry for the file can be found in the map.
    return storeEntries.containsKey(filename);
  }
  public ExportFrontierReportCsvQuery(ServletRequest req) {

    String jobIdStr = UI_FIELD.JOB_ID.getValue(req);
    ArgumentNotValid.checkNotNullOrEmpty(jobIdStr, UI_FIELD.JOB_ID.name());

    jobId = Long.parseLong(jobIdStr);
  }
  /**
   * Initialise the batch job.
   *
   * @param regexp The regexp to match in the crawl.log lines.
   */
  public CrawlLogLinesMatchingRegexp(String regexp) {
    ArgumentNotValid.checkNotNullOrEmpty(regexp, "regexp");
    this.regexp = regexp;

    /** One week in milliseconds. */
    batchJobTimeout = 7 * Constants.ONE_DAY_IN_MILLIES;
  }
  /**
   * Assign a StoreMessage to a specific filename. If the filename is already associated with a
   * StoreMessage, then this StoreMessage will be overwritten by the new StoreMessage.
   *
   * @param filename The name of the file to have a StoreMessage assigned.
   * @param msg The StoreMessage to be assigned to a file.
   * @throws ArgumentNotValid If the StoreMessage is null or if the filename is either null or the
   *     empty string.
   */
  @Override
  public void setReplyInfo(String filename, StoreMessage msg) throws ArgumentNotValid {
    ArgumentNotValid.checkNotNull(msg, "StoreMessage msg");
    ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename");

    // put into the map, and overwrite any existing mapping.
    storeEntries.put(filename, msg);
  }
  /**
   * Retrieves the checksum of a given file.
   *
   * @param filename The name of the file, whose checksum should be retrieved.
   * @return The checksum of the file.
   * @throws ArgumentNotValid If the filename is either null or the empty string.
   */
  @Override
  public String getCheckSum(String filename) throws ArgumentNotValid {
    ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename");

    // Ensure that we have the file requested.
    if (!hasEntry(filename)) {
      throw new UnknownID("Don't know anything about file '" + filename + "'");
    }

    // Retrieve the checksum for a specific entry.
    return database.getChecksum(filename);
  }
  /**
   * Message to signal from a BitarchiveServer to the BitarchiveMonitorServer that the Bit Archive
   * Application identified by BA_ApplicationId has completed its part of the batch job.
   *
   * <p>Holds status information: list of files processed and a list of ARC files (file names) on
   * which the batch job failed.
   *
   * @param to the channel to which this message is to be sent (must be a BAMON channel)
   * @param originatingBatchMsgId the Id field from the original batch message
   * @param status The object containing status info.
   */
  public BatchEndedMessage(ChannelID to, String originatingBatchMsgId, BatchStatus status) {
    super(to, Channels.getError());
    ArgumentNotValid.checkNotNull(to, "to");
    ArgumentNotValid.checkNotNullOrEmpty(originatingBatchMsgId, "String originatingBatchMsgId");
    ArgumentNotValid.checkNotNull(status, "BatchStatus status");

    this.originatingBatchMsgId = originatingBatchMsgId;
    this.baApplicationId = status.getBitArchiveAppId();
    this.rf = status.getResultFile();
    this.noOfFilesProcessed = status.getNoOfFilesProcessed();
    this.filesFailed = status.getFilesFailed();
    this.exceptions = status.getExceptions();
  }
 /**
  * Set the seedlist of the job from the seedList argument. Individual seeds are separated by a
  * '\n' character. Duplicate seeds are removed.
  *
  * @param seedList List of seeds as one String
  */
 public void setSeedList(String seedList) {
   ArgumentNotValid.checkNotNullOrEmpty(seedList, "seedList");
   seedListSet = new HashSet<>();
   BufferedReader reader = new BufferedReader(new StringReader(seedList));
   String seed;
   try {
     while ((seed = reader.readLine()) != null) {
       seedListSet.add(seed); // add to seedlist if not already there
     }
   } catch (IOException e) {
     // This never happens, as we're reading from a string!
     throw new IOFailure("IOException reading from seed string", e);
   } finally {
     IOUtils.closeQuietly(reader);
   }
 }