001package com.box.sdk.internal.pool; 002 003import java.security.NoSuchAlgorithmException; 004import java.util.Map; 005import java.util.Queue; 006import java.util.concurrent.ConcurrentHashMap; 007import java.util.concurrent.LinkedBlockingQueue; 008 009import javax.crypto.Mac; 010 011/** 012 * Reusable thread-safe pool for {@link Mac} instances. 013 * 014 * Example: 015 * 016 * <pre> 017 * {@code 018 * Mac mac = macPool.acquire(); 019 * try { 020 * ... 021 * } finally { 022 * macPool.release(mac); 023 * } 024 * } 025 * </pre> 026 * 027 */ 028public class MacPool { 029 030 /** 031 * Pool of {@link Mac}-s by algorithm. 032 */ 033 private final Map<String, Queue<Mac>> macPoolByAlgorithm = new ConcurrentHashMap<String, Queue<Mac>>(); 034 035 /** 036 * Constructor. 037 */ 038 public MacPool() { 039 } 040 041 /** 042 * Acquires reusable {@link Mac}, has to be also released! 043 * 044 * @param algorithm 045 * {@link Mac#getAlgorithm()} 046 * @return shared {@link Mac} 047 * 048 * @see #release(Mac) 049 */ 050 public Mac acquire(String algorithm) { 051 Mac result = null; 052 053 Queue<Mac> pool = this.macPoolByAlgorithm.get(algorithm); 054 if (pool != null) { 055 result = pool.poll(); 056 } 057 058 if (result != null) { 059 // it has to be synchronized, for the case that some memory parts of Mac provider are changed, 060 // but not yet visible for this thread 061 synchronized (result) { 062 result.reset(); 063 } 064 return result; 065 } 066 067 try { 068 return Mac.getInstance(algorithm); 069 } catch (NoSuchAlgorithmException e) { 070 throw new IllegalArgumentException(String.format("NoSuchAlgorithm '%s':", algorithm), e); 071 } 072 } 073 074 /** 075 * Releases a previously acquired {@link Mac}. 076 * 077 * @param mac 078 * for release 079 * 080 * @see #acquire(String) 081 */ 082 public void release(Mac mac) { 083 Queue<Mac> pool = this.macPoolByAlgorithm.get(mac.getAlgorithm()); 084 if (pool == null) { 085 pool = new LinkedBlockingQueue<Mac>(); 086 this.macPoolByAlgorithm.put(mac.getAlgorithm(), pool); 087 } 088 pool.offer(mac); 089 } 090 091}