10888a09821a98ac0680fad765217302858e70fa4Paul Duffin/* 20888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Copyright (C) 2013 The Guava Authors 30888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 40888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 50888a09821a98ac0680fad765217302858e70fa4Paul Duffin * in compliance with the License. You may obtain a copy of the License at 60888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 70888a09821a98ac0680fad765217302858e70fa4Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0 80888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 90888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Unless required by applicable law or agreed to in writing, software distributed under the License 100888a09821a98ac0680fad765217302858e70fa4Paul Duffin * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 110888a09821a98ac0680fad765217302858e70fa4Paul Duffin * or implied. See the License for the specific language governing permissions and limitations under 120888a09821a98ac0680fad765217302858e70fa4Paul Duffin * the License. 130888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 140888a09821a98ac0680fad765217302858e70fa4Paul Duffin 150888a09821a98ac0680fad765217302858e70fa4Paul Duffinpackage com.google.common.hash; 160888a09821a98ac0680fad765217302858e70fa4Paul Duffin 170888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.base.Preconditions.checkNotNull; 180888a09821a98ac0680fad765217302858e70fa4Paul Duffin 190888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.annotations.Beta; 200888a09821a98ac0680fad765217302858e70fa4Paul Duffin 210888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.io.FilterInputStream; 220888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.io.IOException; 230888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.io.InputStream; 240888a09821a98ac0680fad765217302858e70fa4Paul Duffin 250888a09821a98ac0680fad765217302858e70fa4Paul Duffin/** 260888a09821a98ac0680fad765217302858e70fa4Paul Duffin * An {@link InputStream} that maintains a hash of the data read from it. 270888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 280888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @author Qian Huang 290888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @since 16.0 300888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 310888a09821a98ac0680fad765217302858e70fa4Paul Duffin@Beta 320888a09821a98ac0680fad765217302858e70fa4Paul Duffinpublic final class HashingInputStream extends FilterInputStream { 330888a09821a98ac0680fad765217302858e70fa4Paul Duffin private final Hasher hasher; 340888a09821a98ac0680fad765217302858e70fa4Paul Duffin 350888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 360888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Creates an input stream that hashes using the given {@link HashFunction} and delegates all data 370888a09821a98ac0680fad765217302858e70fa4Paul Duffin * read from it to the underlying {@link InputStream}. 380888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 390888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <p>The {@link InputStream} should not be read from before or after the hand-off. 400888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 410888a09821a98ac0680fad765217302858e70fa4Paul Duffin public HashingInputStream(HashFunction hashFunction, InputStream in) { 420888a09821a98ac0680fad765217302858e70fa4Paul Duffin super(checkNotNull(in)); 430888a09821a98ac0680fad765217302858e70fa4Paul Duffin this.hasher = checkNotNull(hashFunction.newHasher()); 440888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 450888a09821a98ac0680fad765217302858e70fa4Paul Duffin 460888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 470888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Reads the next byte of data from the underlying input stream and updates the hasher with 480888a09821a98ac0680fad765217302858e70fa4Paul Duffin * the byte read. 490888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 500888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 510888a09821a98ac0680fad765217302858e70fa4Paul Duffin public int read() throws IOException { 520888a09821a98ac0680fad765217302858e70fa4Paul Duffin int b = in.read(); 530888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (b != -1) { 540888a09821a98ac0680fad765217302858e70fa4Paul Duffin hasher.putByte((byte) b); 550888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 560888a09821a98ac0680fad765217302858e70fa4Paul Duffin return b; 570888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 580888a09821a98ac0680fad765217302858e70fa4Paul Duffin 590888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 600888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Reads the specified bytes of data from the underlying input stream and updates the hasher with 610888a09821a98ac0680fad765217302858e70fa4Paul Duffin * the bytes read. 620888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 630888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 640888a09821a98ac0680fad765217302858e70fa4Paul Duffin public int read(byte[] bytes, int off, int len) throws IOException { 650888a09821a98ac0680fad765217302858e70fa4Paul Duffin int numOfBytesRead = in.read(bytes, off, len); 660888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (numOfBytesRead != -1) { 670888a09821a98ac0680fad765217302858e70fa4Paul Duffin hasher.putBytes(bytes, off, numOfBytesRead); 680888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 690888a09821a98ac0680fad765217302858e70fa4Paul Duffin return numOfBytesRead; 700888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 710888a09821a98ac0680fad765217302858e70fa4Paul Duffin 720888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 730888a09821a98ac0680fad765217302858e70fa4Paul Duffin * mark() is not supported for HashingInputStream 740888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @return {@code false} always 750888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 760888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 770888a09821a98ac0680fad765217302858e70fa4Paul Duffin public boolean markSupported() { 780888a09821a98ac0680fad765217302858e70fa4Paul Duffin return false; 790888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 800888a09821a98ac0680fad765217302858e70fa4Paul Duffin 810888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 820888a09821a98ac0680fad765217302858e70fa4Paul Duffin * mark() is not supported for HashingInputStream 830888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 840888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 850888a09821a98ac0680fad765217302858e70fa4Paul Duffin public void mark(int readlimit) {} 860888a09821a98ac0680fad765217302858e70fa4Paul Duffin 870888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 880888a09821a98ac0680fad765217302858e70fa4Paul Duffin * reset() is not supported for HashingInputStream. 890888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @throws IOException this operation is not supported 900888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 910888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 920888a09821a98ac0680fad765217302858e70fa4Paul Duffin public void reset() throws IOException { 930888a09821a98ac0680fad765217302858e70fa4Paul Duffin throw new IOException("reset not supported"); 940888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 950888a09821a98ac0680fad765217302858e70fa4Paul Duffin 960888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 970888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Returns the {@link HashCode} based on the data read from this stream. The result is 980888a09821a98ac0680fad765217302858e70fa4Paul Duffin * unspecified if this method is called more than once on the same instance. 990888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 1000888a09821a98ac0680fad765217302858e70fa4Paul Duffin public HashCode hash() { 1010888a09821a98ac0680fad765217302858e70fa4Paul Duffin return hasher.hash(); 1020888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1030888a09821a98ac0680fad765217302858e70fa4Paul Duffin} 104