1
2
3
4
5 package mockit.internal.injection;
6
7 import edu.umd.cs.findbugs.annotations.NonNull;
8 import edu.umd.cs.findbugs.annotations.Nullable;
9
10 import java.lang.reflect.Type;
11 import java.net.URI;
12 import java.net.URISyntaxException;
13 import java.nio.file.Path;
14 import java.security.CodeSource;
15 import java.security.ProtectionDomain;
16
17 import mockit.internal.reflection.GenericTypeReflection;
18 import mockit.internal.util.Utilities;
19
20 public final class TestedClass {
21 @NonNull
22 final Type declaredType;
23 @NonNull
24 final Class<?> declaredClass;
25 @NonNull
26 public final Class<?> targetClass;
27 @NonNull
28 public final GenericTypeReflection reflection;
29 @NonNull
30 final ProtectionDomain protectionDomainOfTestedClass;
31 @Nullable
32 final String codeLocationParentPath;
33 @NonNull
34 public final String nameOfTestedClass;
35 @Nullable
36 public final TestedClass parent;
37 @Nullable
38 public Class<?> testClass;
39
40 public TestedClass(@NonNull Type declaredType, @NonNull Class<?> targetClass) {
41 this(declaredType, targetClass, null);
42 }
43
44 public TestedClass(@NonNull Type declaredType, @NonNull Class<?> targetClass, @Nullable TestedClass parent) {
45 this.declaredType = declaredType;
46 declaredClass = Utilities.getClassType(declaredType);
47 this.targetClass = targetClass;
48 reflection = new GenericTypeReflection(declaredClass, declaredType, false);
49 protectionDomainOfTestedClass = declaredClass.getProtectionDomain();
50 CodeSource codeSource = protectionDomainOfTestedClass.getCodeSource();
51 if (codeSource == null || codeSource.getLocation() == null) {
52 codeLocationParentPath = null;
53 } else {
54 URI location;
55 try {
56 location = codeSource.getLocation().toURI();
57 } catch (URISyntaxException e) {
58 location = null;
59 }
60 codeLocationParentPath = Path.of(location).getParent().toString();
61 }
62 nameOfTestedClass = declaredClass.getName();
63 this.parent = parent;
64 }
65
66 @NonNull
67 public Class<?> getDeclaredClass() {
68 return declaredClass;
69 }
70
71 public boolean isClassFromSameModuleOrSystemAsTestedClass(@NonNull Class<?> anotherClass) {
72 if (anotherClass.getClassLoader() == null) {
73 return false;
74 }
75
76 ProtectionDomain anotherProtectionDomain = anotherClass.getProtectionDomain();
77
78 if (anotherProtectionDomain == null) {
79 return false;
80 }
81
82 if (anotherProtectionDomain == protectionDomainOfTestedClass) {
83 return true;
84 }
85
86 CodeSource anotherCodeSource = anotherProtectionDomain.getCodeSource();
87
88 if (anotherCodeSource == null || anotherCodeSource.getLocation() == null) {
89 return false;
90 }
91
92 if (codeLocationParentPath != null) {
93 try {
94 URI anotherClassPath = anotherCodeSource.getLocation().toURI();
95 String anotherClassParentPath = Path.of(anotherClassPath).getParent().toString();
96
97 if (anotherClassParentPath.equals(codeLocationParentPath)) {
98 return true;
99 }
100 } catch (URISyntaxException e) {
101 return false;
102 }
103 }
104
105 return isInSameSubpackageAsTestedClass(anotherClass);
106 }
107
108 private boolean isInSameSubpackageAsTestedClass(@NonNull Class<?> anotherClass) {
109 String nameOfAnotherClass = anotherClass.getName();
110 int p1 = nameOfAnotherClass.indexOf('.');
111 int p2 = nameOfTestedClass.indexOf('.');
112 boolean differentPackages = p1 != p2 || p1 == -1;
113
114 if (differentPackages) {
115 return false;
116 }
117
118 p1 = nameOfAnotherClass.indexOf('.', p1 + 1);
119 p2 = nameOfTestedClass.indexOf('.', p2 + 1);
120 boolean eitherClassDirectlyInFirstPackageLevel = p1 == -1 || p2 == -1;
121
122 if (eitherClassDirectlyInFirstPackageLevel) {
123 return true;
124 }
125
126 boolean differentSubpackages = p1 != p2;
127
128 return !differentSubpackages && nameOfAnotherClass.substring(0, p1).equals(nameOfTestedClass.substring(0, p2));
129 }
130 }