/*************************GO-LICENSE-START********************************* * Copyright 2014 ThoughtWorks, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *************************GO-LICENSE-END***********************************/ package com.thoughtworks.go.util; import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import com.thoughtworks.go.util.pool.DigestObjectPools; import org.apache.commons.codec.binary.Hex; /** * A replacement for org.apache.commons.codec.digest.DigestUtils , with the MessageDigest Instance cached. * <p/> * This is to avoid the block on the call below which causes performance bottle necks. * java.security.Provider.getService(String, String) * <p/> * http://groups.google.com/group/spymemcached/browse_thread/thread/146bd39fa95cce6a */ public class CachedDigestUtils { private static final int STREAM_BUFFER_LENGTH = 1024; private static DigestObjectPools objectPools = new DigestObjectPools(); private static ConcurrentMap<String, String> shaDigestCache = new ConcurrentHashMap<>(); public static String sha256Hex(String string) { if (shaDigestCache.containsKey(string)) { return shaDigestCache.get(string); } String digest = compute(string, DigestObjectPools.SHA_256); shaDigestCache.putIfAbsent(string, digest); return digest; } public static String md5Hex(String string) { return compute(string, DigestObjectPools.MD_5); } public static String md5Hex(final InputStream data) throws IOException { return objectPools.computeDigest(DigestObjectPools.MD_5, new DigestObjectPools.DigestOperation() { public String perform(MessageDigest digest) throws IOException { byte[] buffer = new byte[STREAM_BUFFER_LENGTH]; int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH); while (read > -1) { digest.update(buffer, 0, read); read = data.read(buffer, 0, STREAM_BUFFER_LENGTH); } return Hex.encodeHexString(digest.digest()); } }); } private static String compute(final String string, String algorithm) { return objectPools.computeDigest(algorithm, new DigestObjectPools.DigestOperation() { public String perform(MessageDigest digest) { digest.update(org.apache.commons.codec.binary.StringUtils.getBytesUtf8(string)); return Hex.encodeHexString(digest.digest()); } }); } }