All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mockit.internal.capturing.CaptureOfImplementations Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 1.7
Show newest version
/*
 * 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.lang.reflect.*;
import java.util.*;

import org.jetbrains.annotations.*;

import mockit.external.asm4.*;
import mockit.external.asm4.Type;
import mockit.internal.*;
import mockit.internal.startup.*;
import mockit.internal.state.*;

public abstract class CaptureOfImplementations implements Runnable
{
   @NotNull private final List captureTransformers;

   protected CaptureOfImplementations() { captureTransformers = new ArrayList(); }

   @NotNull
   protected abstract ClassVisitor createModifier(
      @Nullable ClassLoader cl, @NotNull ClassReader cr, @NotNull String capturedTypeDesc);

   public final void makeSureAllSubtypesAreModified(@NotNull Class baseType)
   {
      makeSureAllSubtypesAreModified(baseType, false);
   }

   public final void makeSureAllSubtypesAreModified(@NotNull Class baseType, boolean registerCapturedClasses)
   {
      if (baseType == TypeVariable.class) {
         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(@NotNull CapturedType captureMetadata, @NotNull String baseTypeDesc)
   {
      Class[] classesLoaded = Startup.instrumentation().getAllLoadedClasses();

      for (Class aClass : classesLoaded) {
         if (captureMetadata.isToBeCaptured(aClass)) {
            redefineClass(aClass, baseTypeDesc);
         }
      }
   }

   private void redefineClass(@NotNull Class realClass, @NotNull 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(@NotNull 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(); }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy