@VisibleForTesting
  static int handleMarkingDocumentSecurity(
      HttpServletRequest req, HttpServletResponse res, Document metadata) throws IOException {
    if (req.getHeader("Authorization") != null) {
      // GSA logged in; it is aware of the access restrictions on the document.
      return HttpServletResponse.SC_OK;
    }

    if (metadata == null) {
      return HttpServletResponse.SC_SERVICE_UNAVAILABLE;
    }

    ValueImpl isPublicVal;
    try {
      isPublicVal = (ValueImpl) Value.getSingleValue(metadata, SpiConstants.PROPNAME_ISPUBLIC);
    } catch (RepositoryException ex) {
      LOGGER.log(Level.WARNING, "Failed retrieving isPublic property", ex);
      return HttpServletResponse.SC_SERVICE_UNAVAILABLE;
    }
    boolean isPublic = isPublicVal == null || isPublicVal.toBoolean();

    if (isSecurityHeaderSupported()) {
      res.setHeader("X-Gsa-Serve-Security", isPublic ? "public" : "secure");
      return HttpServletResponse.SC_OK;
    } else {
      if (isPublic) {
        return HttpServletResponse.SC_OK;
      } else {
        res.setHeader("WWW-Authenticate", "Basic realm=\"Retriever\"");
        return HttpServletResponse.SC_UNAUTHORIZED;
      }
    }
  }
  /**
   * Retrieves the last modified date of a document from a connector instance.
   *
   * @param metadata the Document metadata
   * @return a long integer specifying the time the document was last modified, in milliseconds
   *     since midnight, January 1, 1970 GMT, or -1L if the time is not known
   */
  @VisibleForTesting
  static long handleGetLastModified(Document metadata) {
    if (metadata == null) {
      return -1L;
    }

    try {
      // TODO: Value and DateValue Calendar methods are too weak to try to get
      // last modified from non-DateValues.
      ValueImpl value =
          (ValueImpl) Value.getSingleValue(metadata, SpiConstants.PROPNAME_LASTMODIFIED);
      if (value == null) {
        LOGGER.log(
            Level.FINEST, "Document does not contain {0}", SpiConstants.PROPNAME_LASTMODIFIED);
      } else if (value instanceof DateValue) {
        // DateValues don't give direct access to their Calendar object, but
        // I can get the Calendar back out by parsing the stringized version.
        // This method also applies the FeedTimeZone, if needed.
        // TODO: Add a DateValue.getTimeMillis() or getCalendar() method to
        // directly access the wrapped value.
        String lastModified = ((DateValue) value).toIso8601();
        LOGGER.log(Level.FINEST, "Document last modified {0}", lastModified);
        return Value.iso8601ToCalendar(lastModified).getTimeInMillis();
      }
    } catch (RepositoryException e) {
      LOGGER.log(Level.WARNING, "Failed to retrieve last-modified date", e);
    } catch (ParseException e) {
      LOGGER.log(Level.WARNING, "Failed to parse last-modified date", e);
    }
    return -1L;
  }