View Javadoc
1   /*
2    * Copyright (c) 2006 JMockit developers
3    * This file is subject to the terms of the MIT license (see LICENSE.txt).
4    */
5   package mockit.internal.faking;
6   
7   import static mockit.internal.util.Utilities.getClassType;
8   
9   import edu.umd.cs.findbugs.annotations.NonNull;
10  import edu.umd.cs.findbugs.annotations.Nullable;
11  
12  import java.lang.reflect.Type;
13  
14  import mockit.MockUp;
15  import mockit.asm.classes.ClassReader;
16  import mockit.internal.BaseClassModifier;
17  import mockit.internal.capturing.CaptureOfImplementations;
18  
19  public final class CaptureOfFakedImplementations extends CaptureOfImplementations<Void> {
20      private final FakeClassSetup fakeClassSetup;
21  
22      public CaptureOfFakedImplementations(@NonNull MockUp<?> fake, @NonNull Type baseType) {
23          Class<?> baseClassType = getClassType(baseType);
24          fakeClassSetup = new FakeClassSetup(baseClassType, baseType, fake, null);
25      }
26  
27      @NonNull
28      @Override
29      protected BaseClassModifier createModifier(@Nullable ClassLoader cl, @NonNull ClassReader cr,
30              @NonNull Class<?> baseType, Void typeMetadata) {
31          return fakeClassSetup.createClassModifier(cr);
32      }
33  
34      @Override
35      protected void redefineClass(@NonNull Class<?> realClass, @NonNull byte[] modifiedClass) {
36          fakeClassSetup.applyClassModifications(realClass, modifiedClass);
37      }
38  
39      @Nullable
40      public <T> Class<T> apply() {
41          @SuppressWarnings("unchecked")
42          Class<T> baseType = (Class<T>) fakeClassSetup.realClass;
43          Class<T> baseClassType = baseType;
44          Class<T> fakedClass = null;
45  
46          if (baseType.isInterface()) {
47              fakedClass = new FakedImplementationClass<T>(fakeClassSetup.fake).createImplementation(baseType);
48              baseClassType = fakedClass;
49          }
50  
51          if (baseClassType != Object.class) {
52              redefineClass(baseClassType, baseType, null);
53          }
54  
55          makeSureAllSubtypesAreModified(baseType, false, null);
56          return fakedClass;
57      }
58  }