/*************************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.pool; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class DigestObjectPools { public static final String SHA_256 = "SHA-256"; public static final String MD_5 = "MD5"; private static ThreadLocal<MessageDigest> sha256DigestLocal = new ThreadLocal<>(); private static ThreadLocal<MessageDigest> md5DigestLocal = new ThreadLocal<>(); private final CreateDigest createDigest; public DigestObjectPools() { this(new SimpleCreateDigest()); } public DigestObjectPools(CreateDigest createDigest) { this.createDigest = createDigest; } public String computeDigest(String algorithm, DigestOperation operation) { if (!SHA_256.equals(algorithm) && !MD_5.equals(algorithm)) { throw new IllegalArgumentException("Algorithm not supported"); } try { MessageDigest digest = getDigest(algorithm); String result = operation.perform(digest); digest.reset();//test passes even without this, but can't see sun impl's source, so playing safe return result; } catch (Exception e) { throw new RuntimeException("Failed to compute the digest.", e); } } private MessageDigest getDigest(String algorithm) throws Exception { ThreadLocal<MessageDigest> messageDigestThreadLocal = get(algorithm); MessageDigest digest = messageDigestThreadLocal.get(); if (digest == null) { digest = createDigest.create(algorithm); messageDigestThreadLocal.set(digest); } return digest; } private ThreadLocal<MessageDigest> get(String algorithm) { if (SHA_256.equals(algorithm)) { return sha256DigestLocal; } if (MD_5.equals(algorithm)) { return md5DigestLocal; } throw new IllegalArgumentException("Algorithm not supported"); } public static interface DigestOperation { public String perform(MessageDigest digest) throws IOException; } public static interface CreateDigest { public MessageDigest create(String algorithm) throws NoSuchAlgorithmException; } private static class SimpleCreateDigest implements CreateDigest { public MessageDigest create(String algorithm) throws NoSuchAlgorithmException { return MessageDigest.getInstance(algorithm); } } /** * @deprecated Used only in tests */ void clearThreadLocals() { sha256DigestLocal.set(null); md5DigestLocal.set(null); } }