• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / jmockit1 / 381

28 Oct 2025 02:00PM UTC coverage: 72.226% (-1.0%) from 73.269%
381

push

github

web-flow
Merge pull request #393 from hazendaz/full-jakarta-support

Jakarta Full Migration

5686 of 8360 branches covered (68.01%)

Branch coverage included in aggregate %.

145 of 408 new or added lines in 14 files covered. (35.54%)

19 existing lines in 4 files now uncovered.

11948 of 16055 relevant lines covered (74.42%)

0.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.44
/main/src/main/java/mockit/internal/capturing/CaptureTransformer.java
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.capturing;
6

7
import static mockit.internal.capturing.CapturedType.isNotToBeCaptured;
8

9
import edu.umd.cs.findbugs.annotations.NonNull;
10
import edu.umd.cs.findbugs.annotations.Nullable;
11

12
import java.lang.instrument.ClassFileTransformer;
13
import java.security.ProtectionDomain;
14
import java.util.Collections;
15
import java.util.HashMap;
16
import java.util.Map;
17

18
import mockit.asm.classes.ClassReader;
19
import mockit.asm.classes.ClassVisitor;
20
import mockit.asm.metadata.ClassMetadataReader;
21
import mockit.asm.types.JavaType;
22
import mockit.internal.ClassFile;
23
import mockit.internal.ClassIdentification;
24
import mockit.internal.startup.Startup;
25
import mockit.internal.state.TestRun;
26

27
public final class CaptureTransformer<M> implements ClassFileTransformer {
28
    @NonNull
29
    private final CapturedType capturedType;
30
    @NonNull
31
    private final String capturedTypeDesc;
32
    @NonNull
33
    private final CaptureOfImplementations<M> captureOfImplementations;
34
    @NonNull
35
    private final Map<ClassIdentification, byte[]> transformedClasses;
36
    @NonNull
37
    private final Map<String, Boolean> superTypesSearched;
38
    @Nullable
39
    private final M typeMetadata;
40
    private boolean inactive;
41

42
    CaptureTransformer(@NonNull CapturedType capturedType,
43
            @NonNull CaptureOfImplementations<M> captureOfImplementations, boolean registerTransformedClasses,
44
            @Nullable M typeMetadata) {
1✔
45
        this.capturedType = capturedType;
1✔
46
        capturedTypeDesc = JavaType.getInternalName(capturedType.baseType);
1✔
47
        this.captureOfImplementations = captureOfImplementations;
1✔
48
        transformedClasses = registerTransformedClasses ? new HashMap<>(2)
1✔
49
                : Collections.<ClassIdentification, byte[]> emptyMap();
1✔
50
        superTypesSearched = new HashMap<>();
1✔
51
        this.typeMetadata = typeMetadata;
1✔
52
    }
1✔
53

54
    public void deactivate() {
55
        inactive = true;
1✔
56

57
        if (!transformedClasses.isEmpty()) {
1✔
58
            for (Map.Entry<ClassIdentification, byte[]> classNameAndOriginalBytecode : transformedClasses.entrySet()) {
1✔
59
                ClassIdentification classId = classNameAndOriginalBytecode.getKey();
1✔
60
                byte[] originalBytecode = classNameAndOriginalBytecode.getValue();
1✔
61

62
                Startup.redefineMethods(classId, originalBytecode);
1✔
63
            }
1✔
64

65
            transformedClasses.clear();
1✔
66
        }
67
    }
1✔
68

69
    @Nullable
70
    @Override
71
    public byte[] transform(@Nullable ClassLoader loader, @NonNull String classDesc,
72
            @Nullable Class<?> classBeingRedefined, @Nullable ProtectionDomain protectionDomain,
73
            @NonNull byte[] classfileBuffer) {
74
        if (classBeingRedefined != null || inactive || isNotToBeCaptured(protectionDomain, classDesc)) {
1!
75
            return null;
1✔
76
        }
77

78
        if (isClassToBeCaptured(loader, classfileBuffer)) {
1✔
79
            String className = classDesc.replace('/', '.');
1✔
80
            ClassReader cr = new ClassReader(classfileBuffer);
1✔
81
            return modifyAndRegisterClass(loader, className, cr);
1✔
82
        }
83

84
        return null;
1✔
85
    }
86

87
    private boolean isClassToBeCaptured(@Nullable ClassLoader loader, @NonNull byte[] classfileBuffer) {
88
        ClassMetadataReader cmr = new ClassMetadataReader(classfileBuffer);
1✔
89
        String superName = cmr.getSuperClass();
1✔
90

91
        if (capturedTypeDesc.equals(superName)) {
1✔
92
            return true;
1✔
93
        }
94

95
        String[] interfaces = cmr.getInterfaces();
1✔
96

97
        if (interfaces != null && isClassWhichImplementsACapturingInterface(interfaces)) {
1✔
98
            return true;
1✔
99
        }
100

101
        return superName != null && searchSuperTypes(loader, superName, interfaces);
1!
102
    }
103

104
    private boolean isClassWhichImplementsACapturingInterface(@NonNull String[] interfaces) {
105
        for (String implementedInterface : interfaces) {
1✔
106
            if (capturedTypeDesc.equals(implementedInterface)) {
1✔
107
                return true;
1✔
108
            }
109
        }
110

111
        return false;
1✔
112
    }
113

114
    private boolean searchSuperTypes(@Nullable ClassLoader loader, @NonNull String superName,
115
            @Nullable String[] interfaces) {
116
        if (!"java/lang/Object".equals(superName) && !superName.startsWith("mockit/")
1✔
117
                && searchSuperType(loader, superName)) {
1✔
118
            return true;
1✔
119
        }
120

121
        if (interfaces != null && interfaces.length > 0) {
1!
122
            for (String itf : interfaces) {
1✔
123
                if (!itf.startsWith("java/") && !itf.startsWith("javax/") && !itf.startsWith("jakarta/")
1!
124
                        && searchSuperType(loader, itf)) {
1!
UNCOV
125
                    return true;
×
126
                }
127
            }
128
        }
129

130
        return false;
1✔
131
    }
132

133
    private boolean searchSuperType(@Nullable ClassLoader loader, @NonNull String superName) {
134
        Boolean extendsCapturedType = superTypesSearched.get(superName);
1✔
135

136
        if (extendsCapturedType == null) {
1✔
137
            byte[] classfileBytes = ClassFile.getClassFile(loader, superName);
1✔
138
            extendsCapturedType = isClassToBeCaptured(loader, classfileBytes);
1✔
139
            superTypesSearched.put(superName, extendsCapturedType);
1✔
140
        }
141

142
        return extendsCapturedType;
1✔
143
    }
144

145
    @NonNull
146
    private byte[] modifyAndRegisterClass(@Nullable ClassLoader loader, @NonNull String className,
147
            @NonNull ClassReader cr) {
148
        ClassVisitor modifier = captureOfImplementations.createModifier(loader, cr, capturedType.baseType,
1✔
149
                typeMetadata);
150
        cr.accept(modifier);
1✔
151

152
        ClassIdentification classId = new ClassIdentification(loader, className);
1✔
153
        byte[] originalBytecode = cr.getBytecode();
1✔
154

155
        if (transformedClasses == Collections.<ClassIdentification, byte[]> emptyMap()) {
1✔
156
            TestRun.mockFixture().addTransformedClass(classId, originalBytecode);
1✔
157
        } else {
158
            transformedClasses.put(classId, originalBytecode);
1✔
159
        }
160

161
        TestRun.mockFixture().registerMockedClass(capturedType.baseType);
1✔
162
        return modifier.toByteArray();
1✔
163
    }
164

165
    @Nullable
166
    public <C extends CaptureOfImplementations<?>> C getCaptureOfImplementationsIfApplicable(@NonNull Class<?> aType) {
167
        if (typeMetadata != null && capturedType.baseType.isAssignableFrom(aType)) {
1!
168
            // noinspection unchecked
169
            return (C) captureOfImplementations;
1✔
170
        }
171

172
        return null;
1✔
173
    }
174

175
    public boolean areCapturedClasses(@NonNull Class<?> mockedClass1, @NonNull Class<?> mockedClass2) {
176
        Class<?> baseType = capturedType.baseType;
1✔
177
        return baseType.isAssignableFrom(mockedClass1) && baseType.isAssignableFrom(mockedClass2);
1✔
178
    }
179
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc