package org.limewire.security;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Class that hides the rotation of private keys.
*/
class MACCalculatorRotator implements MACCalculatorRepository {
private final SettingsProvider provider;
private final MACCalculatorFactory factory;
private final ScheduledExecutorService scheduler;
private MACCalculator current, old;
private final Runnable rotator, expirer;
/**
* @param scheduler a <tt>SchedulingThreadPool</tt> that will execute the rotation
* @param factory something that creates the QKGenerators
* @param provider a <tt>SettingsProvider</tt>. The change period must be bigger
* than the grace period.
*/
MACCalculatorRotator(ScheduledExecutorService scheduler,
MACCalculatorFactory factory,
SettingsProvider provider) {
this.provider = provider;
this.factory = factory;
this.scheduler = scheduler;
if (provider.getGracePeriod() >= provider.getChangePeriod())
throw new IllegalArgumentException("settings not supported");
rotator = new Runnable() {
public void run() {
rotate();
}
};
expirer = new Runnable() {
public void run() {
expireOld();
}
};
rotate();
}
public synchronized MACCalculator[] getValidMACCalculators() {
if (old == null)
return new MACCalculator[]{current};
else
return new MACCalculator[]{current, old};
}
public synchronized MACCalculator getCurrentMACCalculator() {
return current;
}
private void rotate() {
MACCalculator newKQ = factory.createMACCalculator();
synchronized(this) {
old = current;
current = newKQ;
}
scheduler.schedule(rotator, provider.getChangePeriod(), TimeUnit.MILLISECONDS);
scheduler.schedule(expirer, provider.getGracePeriod(), TimeUnit.MILLISECONDS);
}
private synchronized void expireOld() {
old = null;
}
}