package org.pitest.mutationtest.execute;
import org.pitest.boot.HotSwapAgent;
import org.pitest.classinfo.ClassByteArraySource;
import org.pitest.classinfo.ClassName;
import org.pitest.functional.F3;
import org.pitest.util.Unchecked;
class HotSwap implements F3<ClassName, ClassLoader, byte[], Boolean> {
private final ClassByteArraySource byteSource;
private byte[] lastClassPreMutation;
private ClassName lastMutatedClass;
private ClassLoader lastUsedLoader;
HotSwap(final ClassByteArraySource byteSource) {
this.byteSource = byteSource;
}
@Override
public Boolean apply(final ClassName clazzName, final ClassLoader loader,
final byte[] b) {
Class<?> clazz;
try {
restoreLastClass(this.byteSource, clazzName, loader);
this.lastUsedLoader = loader;
clazz = Class.forName(clazzName.asJavaName(), false, loader);
return HotSwapAgent.hotSwap(clazz, b);
} catch (final ClassNotFoundException e) {
throw Unchecked.translateCheckedException(e);
}
}
private void restoreLastClass(final ClassByteArraySource byteSource,
final ClassName clazzName, final ClassLoader loader)
throws ClassNotFoundException {
if ((this.lastMutatedClass != null)
&& !this.lastMutatedClass.equals(clazzName)) {
restoreForLoader(this.lastUsedLoader);
restoreForLoader(loader);
}
if ((this.lastMutatedClass == null)
|| !this.lastMutatedClass.equals(clazzName)) {
this.lastClassPreMutation = byteSource.getBytes(clazzName.asJavaName())
.value();
}
this.lastMutatedClass = clazzName;
}
private void restoreForLoader(ClassLoader loader)
throws ClassNotFoundException {
Class<?> clazz = Class.forName(this.lastMutatedClass.asJavaName(), false,
loader);
HotSwapAgent.hotSwap(clazz, this.lastClassPreMutation);
}
}