package org.commcare.models.encryption;
import android.util.Log;
import java.util.HashSet;
import java.util.Stack;
import javax.crypto.Cipher;
/**
* @author ctsims
*/
public abstract class CipherPool {
private static final String TAG = CipherPool.class.getSimpleName();
private static final int GROWTH_FACTOR = 5;
private final HashSet<Cipher> issued = new HashSet<>();
private final Stack<Cipher> free = new Stack<>();
//TODO: Pass in factory and finalize all API's rather than
//leaving the class to be anonymous?
public CipherPool() {
}
public synchronized final void init() {
grow();
}
public synchronized final Cipher borrow() {
if (free.isEmpty()) {
grow();
Log.d(TAG, "Growing cipher pool. Current size is: " + free.size() + issued.size());
}
Cipher toLend = free.pop();
issued.add(toLend);
return toLend;
}
public synchronized final void remit(Cipher cipher) {
issued.remove(cipher);
free.push(cipher);
}
private synchronized void grow() {
for (int i = 0; i < GROWTH_FACTOR; ++i) {
free.push(generateNewCipher());
}
}
protected abstract Cipher generateNewCipher();
public synchronized final void expire() {
//do we want to try to destroy the final object here?
issued.clear();
free.clear();
}
}