Coverage Summary for Class: MessageDigestHashFunction (com.google.common.hash)
| Class | Method, % | Line, % |
|---|---|---|
| MessageDigestHashFunction | 0% (0/8) | 0% (0/26) |
| MessageDigestHashFunction$MessageDigestHasher | 0% (0/7) | 0% (0/16) |
| MessageDigestHashFunction$SerializedForm | 0% (0/3) | 0% (0/6) |
| Total | 0% (0/18) | 0% (0/48) |
1 /* 2 * Copyright (C) 2011 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15 package com.google.common.hash; 16 17 import static com.google.common.base.Preconditions.checkArgument; 18 import static com.google.common.base.Preconditions.checkNotNull; 19 import static com.google.common.base.Preconditions.checkState; 20 21 import com.google.errorprone.annotations.Immutable; 22 import java.io.Serializable; 23 import java.nio.ByteBuffer; 24 import java.security.MessageDigest; 25 import java.security.NoSuchAlgorithmException; 26 import java.util.Arrays; 27 28 /** 29 * {@link HashFunction} adapter for {@link MessageDigest} instances. 30 * 31 * @author Kevin Bourrillion 32 * @author Dimitris Andreou 33 */ 34 @Immutable 35 @ElementTypesAreNonnullByDefault 36 final class MessageDigestHashFunction extends AbstractHashFunction implements Serializable { 37 38 @SuppressWarnings("Immutable") // cloned before each use 39 private final MessageDigest prototype; 40 41 private final int bytes; 42 private final boolean supportsClone; 43 private final String toString; 44 45 MessageDigestHashFunction(String algorithmName, String toString) { 46 this.prototype = getMessageDigest(algorithmName); 47 this.bytes = prototype.getDigestLength(); 48 this.toString = checkNotNull(toString); 49 this.supportsClone = supportsClone(prototype); 50 } 51 52 MessageDigestHashFunction(String algorithmName, int bytes, String toString) { 53 this.toString = checkNotNull(toString); 54 this.prototype = getMessageDigest(algorithmName); 55 int maxLength = prototype.getDigestLength(); 56 checkArgument( 57 bytes >= 4 && bytes <= maxLength, "bytes (%s) must be >= 4 and < %s", bytes, maxLength); 58 this.bytes = bytes; 59 this.supportsClone = supportsClone(prototype); 60 } 61 62 private static boolean supportsClone(MessageDigest digest) { 63 try { 64 digest.clone(); 65 return true; 66 } catch (CloneNotSupportedException e) { 67 return false; 68 } 69 } 70 71 @Override 72 public int bits() { 73 return bytes * Byte.SIZE; 74 } 75 76 @Override 77 public String toString() { 78 return toString; 79 } 80 81 private static MessageDigest getMessageDigest(String algorithmName) { 82 try { 83 return MessageDigest.getInstance(algorithmName); 84 } catch (NoSuchAlgorithmException e) { 85 throw new AssertionError(e); 86 } 87 } 88 89 @Override 90 public Hasher newHasher() { 91 if (supportsClone) { 92 try { 93 return new MessageDigestHasher((MessageDigest) prototype.clone(), bytes); 94 } catch (CloneNotSupportedException e) { 95 // falls through 96 } 97 } 98 return new MessageDigestHasher(getMessageDigest(prototype.getAlgorithm()), bytes); 99 } 100 101 private static final class SerializedForm implements Serializable { 102 private final String algorithmName; 103 private final int bytes; 104 private final String toString; 105 106 private SerializedForm(String algorithmName, int bytes, String toString) { 107 this.algorithmName = algorithmName; 108 this.bytes = bytes; 109 this.toString = toString; 110 } 111 112 private Object readResolve() { 113 return new MessageDigestHashFunction(algorithmName, bytes, toString); 114 } 115 116 private static final long serialVersionUID = 0; 117 } 118 119 Object writeReplace() { 120 return new SerializedForm(prototype.getAlgorithm(), bytes, toString); 121 } 122 123 /** Hasher that updates a message digest. */ 124 private static final class MessageDigestHasher extends AbstractByteHasher { 125 private final MessageDigest digest; 126 private final int bytes; 127 private boolean done; 128 129 private MessageDigestHasher(MessageDigest digest, int bytes) { 130 this.digest = digest; 131 this.bytes = bytes; 132 } 133 134 @Override 135 protected void update(byte b) { 136 checkNotDone(); 137 digest.update(b); 138 } 139 140 @Override 141 protected void update(byte[] b, int off, int len) { 142 checkNotDone(); 143 digest.update(b, off, len); 144 } 145 146 @Override 147 protected void update(ByteBuffer bytes) { 148 checkNotDone(); 149 digest.update(bytes); 150 } 151 152 private void checkNotDone() { 153 checkState(!done, "Cannot re-use a Hasher after calling hash() on it"); 154 } 155 156 @Override 157 public HashCode hash() { 158 checkNotDone(); 159 done = true; 160 return (bytes == digest.getDigestLength()) 161 ? HashCode.fromBytesNoCopy(digest.digest()) 162 : HashCode.fromBytesNoCopy(Arrays.copyOf(digest.digest(), bytes)); 163 } 164 } 165 }