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