/*
* Copyright (c) 2006 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.internal.mockups;
import java.lang.reflect.*;
import java.lang.reflect.Type;
import javax.annotation.*;
import static java.lang.reflect.Modifier.*;
import mockit.*;
import mockit.external.asm.*;
import mockit.internal.classGeneration.*;
import mockit.internal.util.*;
public final class MockedImplementationClass<T>
{
private static final ClassLoader THIS_CL = MockedImplementationClass.class.getClassLoader();
@Nonnull private final MockUp<?> mockUpInstance;
@Nullable private ImplementationClass<T> implementationClass;
private Class<T> generatedClass;
public MockedImplementationClass(@Nonnull MockUp<?> mockUpInstance) { this.mockUpInstance = mockUpInstance; }
@Nonnull
public Class<T> createImplementation(@Nonnull Class<T> interfaceToBeMocked, @Nullable Type typeToMock)
{
createImplementation(interfaceToBeMocked);
byte[] generatedBytecode = implementationClass == null ? null : implementationClass.getGeneratedBytecode();
MockClassSetup mockClassSetup = new MockClassSetup(generatedClass, typeToMock, mockUpInstance, generatedBytecode);
mockClassSetup.redefineMethodsInGeneratedClass();
return generatedClass;
}
@Nonnull
Class<T> createImplementation(@Nonnull Class<T> interfaceToBeMocked)
{
if (isPublic(interfaceToBeMocked.getModifiers())) {
generateImplementationForPublicInterface(interfaceToBeMocked);
}
else {
//noinspection unchecked
generatedClass = (Class<T>) Proxy.getProxyClass(interfaceToBeMocked.getClassLoader(), interfaceToBeMocked);
}
return generatedClass;
}
private void generateImplementationForPublicInterface(@Nonnull Class<T> interfaceToBeMocked)
{
implementationClass = new ImplementationClass<T>(interfaceToBeMocked) {
@Nonnull @Override
protected ClassVisitor createMethodBodyGenerator(@Nonnull ClassReader typeReader)
{
return new InterfaceImplementationGenerator(typeReader, generatedClassName);
}
};
generatedClass = implementationClass.generateClass();
}
@Nonnull
public Class<T> createImplementation(@Nonnull Type[] interfacesToBeMocked)
{
Class<?>[] interfacesToMock = new Class<?>[interfacesToBeMocked.length];
for (int i = 0; i < interfacesToMock.length; i++) {
interfacesToMock[i] = Utilities.getClassType(interfacesToBeMocked[i]);
}
//noinspection unchecked
generatedClass = (Class<T>) Proxy.getProxyClass(THIS_CL, interfacesToMock);
new MockClassSetup(generatedClass, null, mockUpInstance, null).redefineMethods();
return generatedClass;
}
}