private static void assertMessageDigestHashing(byte[] input, String algorithmName) {
   try {
     MessageDigest digest = MessageDigest.getInstance(algorithmName);
     assertEquals(
         HashCode.fromBytes(digest.digest(input)), ALGORITHMS.get(algorithmName).hashBytes(input));
     for (int bytes = 4; bytes <= digest.getDigestLength(); bytes++) {
       assertEquals(
           HashCode.fromBytes(Arrays.copyOf(digest.digest(input), bytes)),
           new MessageDigestHashFunction(algorithmName, bytes, algorithmName).hashBytes(input));
     }
     try {
       int maxSize = digest.getDigestLength();
       new MessageDigestHashFunction(algorithmName, maxSize + 1, algorithmName);
       fail();
     } catch (IllegalArgumentException expected) {
     }
   } catch (NoSuchAlgorithmException nsae) {
     throw new AssertionError(nsae);
   }
 }
 @Override
 public void endElement(String uri, String name, String qName) {
   if (qName.equals("Id")) {
     this.id = currentOrNull(currentText);
   } else if (qName.equals("MessageId")) {
     builder.id(currentOrNull(currentText));
   } else if (qName.equals("MD5OfMessageBody")) {
     builder.md5(HashCode.fromBytes(base16().lowerCase().decode(currentOrNull(currentText))));
   }
   currentText.setLength(0);
 }
 @Override
 public AsyncLeaderElector newAsyncLeaderElector(String name) {
   checkNotNull(name);
   Map<PartitionId, AsyncLeaderElector> leaderElectors =
       Maps.transformValues(members, partition -> partition.newAsyncLeaderElector(name));
   Hasher<String> hasher =
       topic -> {
         long hashCode = HashCode.fromBytes(topic.getBytes(Charsets.UTF_8)).asLong();
         return sortedMemberPartitionIds.get(Hashing.consistentHash(hashCode, members.size()));
       };
   return new PartitionedAsyncLeaderElector(name, leaderElectors, hasher);
 }
 @Override
 public <K, V> AsyncConsistentMap<K, V> newAsyncConsistentMap(String name, Serializer serializer) {
   checkNotNull(name);
   checkNotNull(serializer);
   Map<PartitionId, AsyncConsistentMap<K, V>> maps =
       Maps.transformValues(
           members, partition -> partition.newAsyncConsistentMap(name, serializer));
   Hasher<K> hasher =
       key -> {
         long hashCode =
             HashCode.fromBytes(Bytes.ensureCapacity(serializer.encode(key), 8, 0)).asLong();
         return sortedMemberPartitionIds.get(Hashing.consistentHash(hashCode, members.size()));
       };
   return new PartitionedAsyncConsistentMap<>(name, maps, hasher);
 }
  @Override
  public Blob getBlob(final String container, final String key) {
    BlobBuilder builder = blobBuilders.get();
    builder.name(key);
    File file = getFileForBlobKey(container, key);
    ByteSource byteSource;

    if (getDirectoryBlobSuffix(key) != null) {
      logger.debug("%s - %s is a directory", container, key);
      byteSource = ByteSource.empty();
    } else {
      byteSource = Files.asByteSource(file);
    }
    try {
      String cacheControl = null;
      String contentDisposition = null;
      String contentEncoding = null;
      String contentLanguage = null;
      String contentType = null;
      HashCode hashCode = null;
      Date expires = null;
      ImmutableMap.Builder<String, String> userMetadata = ImmutableMap.builder();

      UserDefinedFileAttributeView view = getUserDefinedFileAttributeView(file.toPath());
      if (view != null) {
        Set<String> attributes = ImmutableSet.copyOf(view.list());

        cacheControl = readStringAttributeIfPresent(view, attributes, XATTR_CACHE_CONTROL);
        contentDisposition =
            readStringAttributeIfPresent(view, attributes, XATTR_CONTENT_DISPOSITION);
        contentEncoding = readStringAttributeIfPresent(view, attributes, XATTR_CONTENT_ENCODING);
        contentLanguage = readStringAttributeIfPresent(view, attributes, XATTR_CONTENT_LANGUAGE);
        contentType = readStringAttributeIfPresent(view, attributes, XATTR_CONTENT_TYPE);
        if (contentType == null && autoDetectContentType) {
          contentType = probeContentType(file.toPath());
        }
        if (attributes.contains(XATTR_CONTENT_MD5)) {
          ByteBuffer buf = ByteBuffer.allocate(view.size(XATTR_CONTENT_MD5));
          view.read(XATTR_CONTENT_MD5, buf);
          hashCode = HashCode.fromBytes(buf.array());
        }
        if (attributes.contains(XATTR_EXPIRES)) {
          ByteBuffer buf = ByteBuffer.allocate(view.size(XATTR_EXPIRES));
          view.read(XATTR_EXPIRES, buf);
          buf.flip();
          expires = new Date(buf.asLongBuffer().get());
        }
        for (String attribute : attributes) {
          if (!attribute.startsWith(XATTR_USER_METADATA_PREFIX)) {
            continue;
          }
          String value = readStringAttributeIfPresent(view, attributes, attribute);
          userMetadata.put(attribute.substring(XATTR_USER_METADATA_PREFIX.length()), value);
        }

        builder
            .payload(byteSource)
            .cacheControl(cacheControl)
            .contentDisposition(contentDisposition)
            .contentEncoding(contentEncoding)
            .contentLanguage(contentLanguage)
            .contentLength(byteSource.size())
            .contentMD5(hashCode)
            .contentType(contentType)
            .expires(expires)
            .userMetadata(userMetadata.build());
      } else {
        builder
            .payload(byteSource)
            .contentLength(byteSource.size())
            .contentMD5(byteSource.hash(Hashing.md5()).asBytes());
      }
    } catch (IOException e) {
      throw Throwables.propagate(e);
    }
    Blob blob = builder.build();
    blob.getMetadata().setContainer(container);
    blob.getMetadata().setLastModified(new Date(file.lastModified()));
    blob.getMetadata().setSize(file.length());
    if (blob.getPayload().getContentMetadata().getContentMD5() != null)
      blob.getMetadata()
          .setETag(
              base16().lowerCase().encode(blob.getPayload().getContentMetadata().getContentMD5()));
    return blob;
  }