mockit.internal.capturing.CaptureOfImplementations Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jmockit Show documentation
Show all versions of jmockit Show documentation
JMockit is a Java toolkit for developer (unit/integration) testing.
It contains mocking APIs and other tools, supporting both JUnit and TestNG.
The mocking APIs allow all kinds of Java code, without testability restrictions, to be tested
in isolation from selected dependencies.
/*
* Copyright (c) 2006-2013 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.internal.capturing;
import java.util.*;
import mockit.external.asm4.*;
import mockit.internal.*;
import mockit.internal.startup.*;
import mockit.internal.state.*;
public abstract class CaptureOfImplementations implements Runnable
{
private final List captureTransformers;
protected CaptureOfImplementations() { captureTransformers = new ArrayList(); }
protected abstract ClassVisitor createModifier(ClassLoader cl, ClassReader cr, String capturedTypeDesc);
public final void makeSureAllSubtypesAreModified(Class> baseType)
{
makeSureAllSubtypesAreModified(baseType, false);
}
public final void makeSureAllSubtypesAreModified(Class> baseType, boolean registerCapturedClasses)
{
if (baseType == null) {
throw new IllegalArgumentException("Capturing implementations of multiple base types is not supported");
}
String baseTypeDesc = Type.getInternalName(baseType);
CapturedType captureMetadata = new CapturedType(baseType);
redefineClassesAlreadyLoaded(captureMetadata, baseTypeDesc);
createCaptureTransformer(captureMetadata, registerCapturedClasses);
}
private void redefineClassesAlreadyLoaded(CapturedType captureMetadata, String baseTypeDesc)
{
Class>[] classesLoaded = Startup.instrumentation().getAllLoadedClasses();
for (Class> aClass : classesLoaded) {
if (captureMetadata.isToBeCaptured(aClass)) {
redefineClass(aClass, baseTypeDesc);
}
}
}
private void redefineClass(Class> realClass, String baseTypeDesc)
{
if (!TestRun.mockFixture().containsRedefinedClass(realClass)) {
ClassReader classReader;
try {
classReader = ClassFile.createReaderOrGetFromCache(realClass);
}
catch (ClassFile.NotFoundException ignore) {
return;
}
ClassVisitor modifier = createModifier(realClass.getClassLoader(), classReader, baseTypeDesc);
classReader.accept(modifier, 0);
byte[] modifiedClass = modifier.toByteArray();
new RedefinitionEngine(realClass).redefineMethodsWhileRegisteringTheClass(modifiedClass);
}
}
private void createCaptureTransformer(CapturedType captureMetadata, boolean registerCapturedClasses)
{
CaptureTransformer transformer = new CaptureTransformer(captureMetadata, this, registerCapturedClasses);
Startup.instrumentation().addTransformer(transformer);
captureTransformers.add(transformer);
}
public void cleanUp()
{
for (CaptureTransformer transformer : captureTransformers) {
transformer.deactivate();
Startup.instrumentation().removeTransformer(transformer);
}
captureTransformers.clear();
}
public final void run() { cleanUp(); }
}