All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fizzed.crux.util.Hasher Maven / Gradle / Ivy

There is a newer version: 1.0.46
Show newest version
package com.fizzed.crux.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

abstract public class Hasher {
 
    /**
     * Updates the hash/digest with the supplied byte buffer. The hasher must
     * still be OPEN otherwise this will throw an exception.
     * @param buffer
     * @return 
     */
    abstract public Hasher update(ByteBuffer buffer);
    
    /**
     * Updates the hash/digest with the supplied byte buffer. The hasher must
     * still be OPEN otherwise this will throw an exception.
     * @param buffer
     * @return 
     */
    abstract public Hasher update(byte[] buffer);
    
    /**
     * Updates the hash/digest with the supplied byte buffer. The hasher must
     * still be OPEN otherwise this will throw an exception.
     * @param buffer
     * @param offset
     * @param length
     * @return 
     */
    abstract public Hasher update(byte[] buffer, int offset, int length);
    
    abstract public boolean isCompleted();
    
    /**
     * Closes the hasher (if not yet closed) and returns the result as bytes.
     * @return 
     */
    abstract public byte[] asBytes();
    
    /**
     * Closes the hasher (if not yet closed) and returns the result as a hex-encoded
     * value
     * @return 
     */
    abstract public String asHex();
    
    /**
     * Creates a new (open) MD5 hasher that is ready to accept a stream of bytes.
     * @return 
     */
    static public Hasher md5() {
        return new Md5Hasher();
    }

    /**
     * Creates a new (closed) MD5 hasher that has computed the digest for the file.
     * @param file The file to compute MD5 digest
     * @return
     * @throws IOException 
     */
    static public Hasher md5(File file) throws IOException {
        return md5(file != null ? file.toPath() : null);
    }
    
    /**
     * Creates a new (closed) MD5 hasher that has computed the digest for the file.
     * @param file The file to compute MD5 digest
     * @return
     * @throws IOException 
     */
    static public Hasher md5(Path file) throws IOException {
        try (InputStream input = Files.newInputStream(file)) {
            return md5(input);
        }
    }
    
    /**
     * Creates a new (closed) MD5 hasher that has computed the digest for the input.
     * @param input The input to compute MD5 digest. The input will be read until
     *      its exhausted. Caller is responsible for closing the input!
     * @return
     * @throws IOException 
     */
    static public Hasher md5(InputStream input) throws IOException {
        final Hasher hasher = md5();
        consume(hasher, input);
        return hasher;
    }
    
    static private void consume(Hasher hasher, InputStream input) throws IOException {
        InOuts.consume(input, (data, read) -> {
            hasher.update(data, 0, read);
        });
    }
    
    static abstract class DigestHasher extends Hasher {

        protected final MessageDigest digest;
        protected byte[] hash;

        protected DigestHasher(String algorithm) {
            try {
                this.digest = MessageDigest.getInstance(algorithm);
            } catch (NoSuchAlgorithmException e) {
                throw new IllegalArgumentException(e.getMessage(), e);
            }
        }

        @Override
        public boolean isCompleted() {
            return this.hash != null;
        }
        
        protected void verifyNotCompleted() {
            if (this.isCompleted()) {
                throw new IllegalStateException("Hasher is completed and cannot be updated");
            }
        }
        
        @Override
        public Hasher update(ByteBuffer buffer) {
            this.verifyNotCompleted();
            this.digest.update(buffer);
            buffer.flip();
            return this;
        }

        @Override
        public Hasher update(byte[] buffer) {
            this.verifyNotCompleted();
            this.digest.update(buffer);
            return this;
        }

        @Override
        public Hasher update(byte[] buffer, int offset, int length) {
            this.verifyNotCompleted();
            this.digest.update(buffer, offset, length);
            return this;
        }

        @Override
        public byte[] asBytes() {
            if (this.hash == null) {
                this.hash = this.digest.digest();
            }
            return this.hash;
        }

        @Override
        public String asHex() {
            return Base16.encode(this.asBytes());
        }

    }
    
    static class Md5Hasher extends DigestHasher {
        
        public Md5Hasher() {
            super("MD5");
        }
        
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy