Adding support for SHA256 for remote execution. Switch remote execution to use
the currently defined hash function for blobs. Some refactoring. Adding an option to set the hash function in the remote worker, defaulting to the current behavior (unfortunately it is a build option, have not found a clean way to specify it at runtime).

BUG=62622420
TESTED=remote worker
RELNOTES: none
PiperOrigin-RevId: 159473116
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java
index 03a0afc..13a7360 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java
@@ -42,14 +42,17 @@
 public abstract class FileSystem {
 
   /** Type of hash function to use for digesting files. */
+  // The underlying HashFunctions are immutable and thread safe.
+  @SuppressWarnings("ImmutableEnumChecker")
   public enum HashFunction {
-    MD5(16),
-    SHA1(20);
+    MD5(Hashing.md5()),
+    SHA1(Hashing.sha1()),
+    SHA256(Hashing.sha256());
 
-    private final int digestSize;
+    private final com.google.common.hash.HashFunction hash;
 
-    HashFunction(int digestSize) {
-      this.digestSize = digestSize;
+    HashFunction(com.google.common.hash.HashFunction hash) {
+      this.hash = hash;
     }
 
     /** Converts to {@link HashFunction}. */
@@ -59,8 +62,12 @@
       }
     }
 
+    public com.google.common.hash.HashFunction getHash() {
+      return hash;
+    }
+
     public boolean isValidDigest(byte[] digest) {
-      return digest != null && digest.length == digestSize;
+      return digest != null && digest.length * 8 == hash.bits();
     }
   }
 
@@ -336,16 +343,16 @@
    *
    * @return a new byte array containing the file's digest
    * @throws IOException if the digest could not be computed for any reason
+   *
+   * Subclasses may (and do) optimize this computation for particular digest functions.
    */
-  protected final byte[] getDigest(final Path path, HashFunction hashFunction) throws IOException {
-    switch(hashFunction) {
-      case MD5:
-        return getMD5Digest(path);
-      case SHA1:
-        return getSHA1Digest(path);
-      default:
-        throw new IOException("Unsupported hash function: " + hashFunction);
-    }
+  protected byte[] getDigest(final Path path, HashFunction hashFunction) throws IOException {
+    return new ByteSource() {
+      @Override
+      public InputStream openStream() throws IOException {
+        return getInputStream(path);
+      }
+    }.hash(hashFunction.getHash()).asBytes();
   }
 
   /**
@@ -354,40 +361,11 @@
    * @return a new byte array containing the file's digest
    * @throws IOException if the digest could not be computed for any reason
    */
-  protected byte[] getDigest(final Path path) throws IOException {
+  protected final byte[] getDigest(final Path path) throws IOException {
     return getDigest(path, digestFunction);
   }
 
   /**
-   * Returns the MD5 digest of the file denoted by {@code path}. See
-   * {@link Path#getMD5Digest} for specification.
-   */
-  protected byte[] getMD5Digest(final Path path) throws IOException {
-    // Naive I/O implementation.  Subclasses may (and do) optimize.
-    // This code is only used by the InMemory or Zip or other weird FSs.
-    return new ByteSource() {
-      @Override
-      public InputStream openStream() throws IOException {
-        return getInputStream(path);
-      }
-    }.hash(Hashing.md5()).asBytes();
-  }
-
-  /**
-   * Returns the MD5 digest of the file denoted by {@code path}. See
-   * {@link Path#getMD5Digest} for specification.
-   */
-  protected byte[] getSHA1Digest(final Path path) throws IOException {
-    // Naive I/O implementation.  TODO(olaola): optimize!
-    return new ByteSource() {
-      @Override
-      public InputStream openStream() throws IOException {
-        return getInputStream(path);
-      }
-    }.hash(Hashing.sha1()).asBytes();
-  }
-
-  /**
    * Returns true if "path" denotes an existing symbolic link. See
    * {@link Path#isSymbolicLink} for specification.
    */