View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package mockit.internal.util;
7   
8   import edu.umd.cs.findbugs.annotations.NonNull;
9   import edu.umd.cs.findbugs.annotations.Nullable;
10  
11  import java.lang.reflect.Proxy;
12  
13  public final class GeneratedClasses {
14      private static final String IMPLCLASS_PREFIX = "$Impl_";
15      private static final String SUBCLASS_PREFIX = "$Subclass_";
16  
17      private GeneratedClasses() {
18      }
19  
20      @NonNull
21      public static String getNameForGeneratedClass(@NonNull Class<?> aClass, @Nullable String suffix) {
22          String prefix = aClass.isInterface() ? IMPLCLASS_PREFIX : SUBCLASS_PREFIX;
23          StringBuilder name = new StringBuilder(60).append(prefix).append(aClass.getSimpleName());
24  
25          if (suffix != null) {
26              name.append('_').append(suffix);
27          }
28  
29          if (aClass.getClassLoader() != null) {
30              Package targetPackage = aClass.getPackage();
31  
32              if (targetPackage != null && !targetPackage.isSealed() && !targetPackage.getName().isEmpty()) {
33                  name.insert(0, '.').insert(0, targetPackage.getName());
34              }
35          }
36  
37          return name.toString();
38      }
39  
40      public static boolean isGeneratedImplementationClass(@NonNull Class<?> mockedType) {
41          return isGeneratedImplementationClassName(mockedType.getName());
42      }
43  
44      public static boolean isGeneratedImplementationClassName(@NonNull String className) {
45          return className.contains(IMPLCLASS_PREFIX);
46      }
47  
48      private static boolean isGeneratedSubclass(@NonNull String className) {
49          return className.contains(SUBCLASS_PREFIX);
50      }
51  
52      public static boolean isExternallyGeneratedSubclass(@NonNull String className) {
53          int p = className.indexOf('$') + 1;
54  
55          // noinspection SimplifiableIfStatement
56          if (p < 2 || p == className.length() || className.charAt(p) != '$') {
57              return false;
58          }
59  
60          return className.contains("_$$_javassist_") || className.contains("_$$_jvst") || className.contains("CGLIB$$");
61      }
62  
63      public static boolean isGeneratedClass(@NonNull String className) {
64          return isGeneratedSubclass(className) || isGeneratedImplementationClassName(className);
65      }
66  
67      @NonNull
68      public static Class<?> getMockedClassOrInterfaceType(@NonNull Class<?> aClass) {
69          if (Proxy.isProxyClass(aClass) || isGeneratedImplementationClass(aClass)) {
70              // Assumes that a proxy class implements a single interface.
71              return aClass.getInterfaces()[0];
72          }
73  
74          if (isGeneratedSubclass(aClass.getName())) {
75              return aClass.getSuperclass();
76          }
77  
78          return aClass;
79      }
80  
81      @NonNull
82      public static Class<?> getMockedClass(@NonNull Object mock) {
83          return getMockedClassOrInterfaceType(mock.getClass());
84      }
85  }