-
Notifications
You must be signed in to change notification settings - Fork 240
/
Copy pathExpectationsTransformer.java
79 lines (64 loc) · 2.56 KB
/
ExpectationsTransformer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
* Copyright (c) 2006 JMockit developers
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.internal.expectations.transformation;
import java.lang.instrument.*;
import java.security.*;
import javax.annotation.*;
import mockit.asm.classes.*;
import mockit.asm.methods.*;
import mockit.internal.util.*;
public final class ExpectationsTransformer implements ClassFileTransformer
{
private static final String BASE_CLASSES =
"mockit/Expectations mockit/Verifications mockit/VerificationsInOrder mockit/FullVerifications";
@Nullable @Override
public byte[] transform(
@Nullable ClassLoader loader, @Nonnull String className, @Nullable Class<?> classBeingRedefined,
@Nullable ProtectionDomain protectionDomain, @Nonnull byte[] classfileBuffer
) {
if (classBeingRedefined == null && protectionDomain != null && className != null) {
boolean anonymousClass = ClassNaming.isAnonymousClass(className);
if (anonymousClass && !isJMockitClass(className) && !className.startsWith("org/junit/")) {
ClassReader cr = new ClassReader(classfileBuffer);
String superClassName = cr.getSuperName();
if (!BASE_CLASSES.contains(superClassName)) {
return null;
}
return modifyInvocationsSubclass(cr, className);
}
}
return null;
}
private static boolean isJMockitClass(@Nonnull String classDesc) {
return
classDesc.startsWith("mockit/") &&
(classDesc.startsWith("mockit/internal/") || classDesc.startsWith("mockit/coverage/") ||
classDesc.startsWith("mockit/integration/"));
}
@Nullable
private static byte[] modifyInvocationsSubclass(@Nonnull ClassReader cr, @Nonnull final String classDesc) {
ClassWriter cw = new ClassWriter(cr);
ClassVisitor modifier = new WrappingClassVisitor(cw) {
@Override
public MethodVisitor visitMethod(
int access, @Nonnull String name, @Nonnull String desc, @Nullable String signature,
@Nullable String[] exceptions)
{
MethodWriter mw = cw.visitMethod(access, name, desc, signature, exceptions);
if (!"<init>".equals(name)) {
return mw;
}
return new InvocationBlockModifier(mw, classDesc);
}
};
try {
cr.accept(modifier);
return modifier.toByteArray();
}
catch (VisitInterruptedException ignore) {}
catch (Throwable e) { e.printStackTrace(); }
return null;
}
}