org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mockito-core Show documentation
Show all versions of mockito-core Show documentation
Mockito mock objects library core API and implementation
/*
* Copyright (c) 2016 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito.internal.creation.bytebuddy;
import net.bytebuddy.TypeCache;
import org.mockito.mock.SerializableMode;
import java.lang.ref.ReferenceQueue;
import java.util.Set;
import java.util.concurrent.Callable;
class TypeCachingBytecodeGenerator extends ReferenceQueue implements BytecodeGenerator {
private final Object BOOTSTRAP_LOCK = new Object();
private final BytecodeGenerator bytecodeGenerator;
private final TypeCache typeCache;
public TypeCachingBytecodeGenerator(BytecodeGenerator bytecodeGenerator, boolean weak) {
this.bytecodeGenerator = bytecodeGenerator;
typeCache = new TypeCache.WithInlineExpunction(weak ? TypeCache.Sort.WEAK : TypeCache.Sort.SOFT);
}
@SuppressWarnings("unchecked")
@Override
public Class mockClass(final MockFeatures params) {
try {
ClassLoader classLoader = params.mockedType.getClassLoader();
return (Class) typeCache.findOrInsert(classLoader,
new MockitoMockKey(params.mockedType, params.interfaces, params.serializableMode, params.stripAnnotations),
new Callable>() {
@Override
public Class call() throws Exception {
return bytecodeGenerator.mockClass(params);
}
}, BOOTSTRAP_LOCK);
} catch (IllegalArgumentException exception) {
Throwable cause = exception.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else {
throw exception;
}
}
}
private static class MockitoMockKey extends TypeCache.SimpleKey {
private final SerializableMode serializableMode;
private final boolean stripAnnotations;
private MockitoMockKey(Class type,
Set> additionalType,
SerializableMode serializableMode,
boolean stripAnnotations) {
super(type, additionalType);
this.serializableMode = serializableMode;
this.stripAnnotations = stripAnnotations;
}
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
if (!super.equals(object)) return false;
MockitoMockKey that = (MockitoMockKey) object;
return stripAnnotations == that.stripAnnotations
&& serializableMode.equals(that.serializableMode);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (stripAnnotations ? 1 : 0);
result = 31 * result + serializableMode.hashCode();
return result;
}
}
}