package jj.util;
import static java.nio.charset.StandardCharsets.UTF_8;
import io.netty.buffer.ByteBuf;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import jj.resource.ResourceThread;
/**
*
* @author jason
*
*/
public enum SHA1Helper {
; // no instances
private static final byte[] DELIMITER = "|".getBytes(UTF_8);
private static final ThreadLocal<MessageDigest> sha1 = new ThreadLocal<MessageDigest>() {
@Override
protected MessageDigest initialValue() {
try {
return MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
throw new AssertionError("couldn't make a MessageDigest", e);
}
}
};
private static String toHex(final byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length);
for (int i = 0; i < bytes.length; i++) {
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
public static String keyFor(final byte[] bytes) {
return toHex(sha1.get().digest(bytes));
}
public static String keyFor(final ByteBuf byteBuf) {
return toHex(sha1.get().digest(byteBuf.array()));
}
public static String keyFor(final ByteBuffer bytes) {
bytes.rewind();
sha1.get().update(bytes);
bytes.rewind();
return toHex(sha1.get().digest());
}
/**
* treats input as UTF-8, adds a delimiter between inputs
* @param strings
* @return
*/
public static String keyFor(final String...strings) {
for (String string : strings) {
if (string != null) {
sha1.get().update(string.getBytes(UTF_8));
sha1.get().update(DELIMITER);
}
}
return toHex(sha1.get().digest());
}
@ResourceThread
public static String keyFor(final Path path) throws IOException {
try (SeekableByteChannel channel = Files.newByteChannel(path)) {
if (channel instanceof FileChannel) {
map(path, (FileChannel)channel);
return toHex(sha1.get().digest());
} else {
return keyFor(Files.readAllBytes(path));
}
}
}
private static void map(final Path path, final FileChannel channel) throws IOException {
MappedByteBuffer buffer = channel.map(MapMode.READ_ONLY, 0, Files.size(path));
sha1.get().update(buffer);
}
}