/**
   * @param request The archive request to handle.
   * @param results The previous identification results for the archive format.
   * @return
   */
  private boolean handleArchive(
      IdentificationRequest request, IdentificationResultCollection results) {

    boolean jobCountDecremented = false;

    String archiveFormat = getArchiveFormat(results);
    if (archiveFormat != null) {
      results.setArchive(true);
      ResourceId id = resultHandler.handle(results);
      jobCounter.incrementPostProcess();
      RequestIdentifier identifier = request.getIdentifier();
      identifier.setResourceId(id);
      if (identifier.getAncestorId() == null) {
        identifier.setAncestorId(id.getId());
      }
      submissionQueue.add(request.getIdentifier());
      jobCounter.decrement();
      jobCountDecremented = true;
      try {
        // BNO: Does this always return the same archive handler for any given container format?
        // And will it end up using the same submission gateway, or a new one with a different
        // thread pool?
        ArchiveHandler handler = archiveHandlerFactory.getHandler(archiveFormat);
        handler.handle(request);
        // CHECKSTYLE:OFF
      } catch (Exception e) {
        // CHECKSTYLE:ON
        String causeMessage = "";
        if (e.getCause() != null) {
          causeMessage = e.getCause().getMessage();
        }
        final String message =
            String.format(
                ARCHIVE_ERROR,
                archiveFormat,
                request.getIdentifier().getUri().toString(),
                e.getMessage(),
                causeMessage);
        log.warn(message);
        resultHandler.handleError(
            new IdentificationException(request, IdentificationErrorType.OTHER, e));
      } finally {
        submissionQueue.remove(request.getIdentifier());
        jobCounter.decrementPostProcess();
      }
    } else {
      ResourceId id = resultHandler.handle(results);
      request.getIdentifier().setNodeId(id.getId());
    }
    return jobCountDecremented;
  }
 private IdentificationResultCollection handleContainer(
     IdentificationRequest request, IdentificationResultCollection results) throws IOException {
   // process a container format (ole2, odf, ooxml etc)
   String containerFormat = getContainerFormat(results);
   try {
     if (containerFormatResolver != null && containerFormat != null) {
       ContainerIdentifier containerIdentifier =
           containerIdentifierFactory.getIdentifier(containerFormat);
       containerIdentifier.setMaxBytesToScan(maxBytesToScan);
       IdentificationResultCollection containerResults = containerIdentifier.submit(request);
       droidCore.removeLowerPriorityHits(containerResults);
       droidCore.checkForExtensionsMismatches(containerResults, request.getExtension());
       containerResults.setFileLength(request.size());
       containerResults.setRequestMetaData(request.getRequestMetaData());
       return containerResults.getResults().isEmpty() ? null : containerResults;
     }
     // CHECKSTYLE:OFF - rules say don't catch this, but other code keeps on throwing them.
     // Don't prejudice any results so far because other code isn't following 'the rules'.
   } catch (Exception e) {
     // CHECKSTYLE:ON
     String causeMessage = "";
     if (e.getCause() != null) {
       causeMessage = e.getCause().getMessage();
     }
     final String message =
         String.format(
             CONTAINER_ERROR,
             containerFormat,
             request.getIdentifier().getUri().toString(),
             e.getMessage(),
             causeMessage);
     log.warn(message);
   }
   return null;
 }
 private void closeRequest() {
   requests.remove(request);
   try {
     request.close();
   } catch (IOException e) {
     log.error(String.format("Error closing request [%s]", request.getIdentifier().getUri()), e);
   }
 }
    @Override
    protected void done() {
      boolean jobCountDecremented = false;
      try {
        generateHash(request);
        IdentificationResultCollection results = get();
        IdentificationResultCollection containerResults = handleContainer(request, results);
        if (containerResults == null) {
          // no container results - process the normal results.
          droidCore.removeLowerPriorityHits(results);
          results = handleExtensions(request, results);

          // Are we processing archive formats?
          if ((processArchives || processWebArchives) && archiveFormatResolver != null) {
            jobCountDecremented = handleArchive(request, results);
          } else { // just process the results so far:
            results.setArchive(getArchiveFormat(results) != null);
            ResourceId id = resultHandler.handle(results);
            request.getIdentifier().setResourceId(id);
          }
        } else { // we have possible container formats:
          droidCore.removeLowerPriorityHits(containerResults);
          containerResults = handleExtensions(request, containerResults);
          ResourceId id = resultHandler.handle(containerResults);
          request.getIdentifier().setResourceId(id);
        }
      } catch (ExecutionException e) {
        final Throwable cause = e.getCause();
        log.error(cause.getStackTrace(), cause);
        resultHandler.handleError(
            new IdentificationException(request, IdentificationErrorType.OTHER, cause));
      } catch (InterruptedException e) {
        log.debug(e);
      } catch (IOException e) {
        resultHandler.handleError(
            new IdentificationException(request, IdentificationErrorType.OTHER, e));
      } finally {
        closeRequest();
        if (!jobCountDecremented) {
          jobCounter.decrement();
        }
      }
    }