• 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

75.75
/main/src/main/java/mockit/internal/injection/InjectionPoint.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.injection;
6

7
import static java.lang.Character.toUpperCase;
8

9
import static mockit.internal.reflection.AnnotationReflection.readAnnotationAttribute;
10
import static mockit.internal.reflection.AnnotationReflection.readAnnotationAttributeIfAvailable;
11
import static mockit.internal.reflection.MethodReflection.invokePublicIfAvailable;
12
import static mockit.internal.reflection.ParameterReflection.NO_PARAMETERS;
13
import static mockit.internal.util.ClassLoad.searchTypeInClasspath;
14

15
import edu.umd.cs.findbugs.annotations.NonNull;
16
import edu.umd.cs.findbugs.annotations.Nullable;
17

18
import java.lang.annotation.Annotation;
19
import java.lang.reflect.AccessibleObject;
20
import java.lang.reflect.Constructor;
21
import java.lang.reflect.GenericArrayType;
22
import java.lang.reflect.ParameterizedType;
23
import java.lang.reflect.Type;
24
import java.lang.reflect.TypeVariable;
25
import java.util.ArrayList;
26
import java.util.Iterator;
27
import java.util.List;
28

29
public final class InjectionPoint {
30
    public enum KindOfInjectionPoint {
1✔
31
        NotAnnotated, Required, Optional
1✔
32
    }
33

34
    @Nullable
35
    public static final Class<?> JAKARTA_CONVERSATION_CLASS;
36
    @Nullable
37
    public static final Class<?> JAVAX_CONVERSATION_CLASS;
38

39
    @Nullable
40
    private static final Class<? extends Annotation> JAKARTA_EJB_CLASS;
41
    @Nullable
42
    private static final Class<? extends Annotation> JAVAX_EJB_CLASS;
43

44
    @Nullable
45
    public static final Class<? extends Annotation> JAKARTA_INJECT_CLASS;
46
    @Nullable
47
    public static final Class<? extends Annotation> JAVAX_INJECT_CLASS;
48

49
    @Nullable
50
    private static final Class<? extends Annotation> JAKARTA_INSTANCE_CLASS;
51
    @Nullable
52
    private static final Class<? extends Annotation> JAVAX_INSTANCE_CLASS;
53

54
    @Nullable
55
    public static final Class<? extends Annotation> JAKARTA_PERSISTENCE_UNIT_CLASS;
56
    @Nullable
57
    public static final Class<? extends Annotation> JAVAX_PERSISTENCE_UNIT_CLASS;
58

59
    @Nullable
60
    public static final Class<? extends Annotation> JAKARTA_POST_CONSTRUCT_CLASS;
61
    @Nullable
62
    public static final Class<? extends Annotation> JAVAX_POST_CONSTRUCT_CLASS;
63

64
    @Nullable
65
    public static final Class<?> JAKARTA_RESOURCE_CLASS;
66
    @Nullable
67
    public static final Class<?> JAVAX_RESOURCE_CLASS;
68

69
    @Nullable
70
    public static final Class<?> JAKARTA_SERVLET_CLASS;
71
    @Nullable
72
    public static final Class<?> JAVAX_SERVLET_CLASS;
73

74
    static {
75
        JAKARTA_CONVERSATION_CLASS = searchTypeInClasspath("jakarta.enterprise.context.Conversation");
1✔
76
        JAVAX_CONVERSATION_CLASS = searchTypeInClasspath("javax.enterprise.context.Conversation");
1✔
77

78
        JAKARTA_EJB_CLASS = searchTypeInClasspath("jakarta.ejb.EJB");
1✔
79
        JAVAX_EJB_CLASS = searchTypeInClasspath("javax.ejb.EJB");
1✔
80

81
        JAKARTA_INJECT_CLASS = searchTypeInClasspath("jakarta.inject.Inject");
1✔
82
        JAVAX_INJECT_CLASS = searchTypeInClasspath("javax.inject.Inject");
1✔
83

84
        JAKARTA_INSTANCE_CLASS = searchTypeInClasspath("jakarta.enterprise.inject.Instance");
1✔
85
        JAVAX_INSTANCE_CLASS = searchTypeInClasspath("javax.enterprise.inject.Instance");
1✔
86

87
        JAKARTA_POST_CONSTRUCT_CLASS = searchTypeInClasspath("jakarta.annotation.PostConstruct");
1✔
88
        JAVAX_POST_CONSTRUCT_CLASS = searchTypeInClasspath("javax.annotation.PostConstruct");
1✔
89

90
        JAKARTA_RESOURCE_CLASS = searchTypeInClasspath("jakarta.annotation.Resource");
1✔
91
        JAVAX_RESOURCE_CLASS = searchTypeInClasspath("javax.annotation.Resource");
1✔
92

93
        JAKARTA_SERVLET_CLASS = searchTypeInClasspath("jakarta.servlet.Servlet");
1✔
94
        JAVAX_SERVLET_CLASS = searchTypeInClasspath("javax.servlet.Servlet");
1✔
95

96
        Class<? extends Annotation> entity = searchTypeInClasspath("jakarta.persistence.Entity");
1✔
97

98
        if (entity == null) {
1!
NEW
99
            JAKARTA_PERSISTENCE_UNIT_CLASS = null;
×
100
        } else {
101
            JAKARTA_PERSISTENCE_UNIT_CLASS = searchTypeInClasspath("jakarta.persistence.PersistenceUnit");
1✔
102
        }
103

104
        entity = searchTypeInClasspath("javax.persistence.Entity");
1✔
105

106
        if (entity == null) {
1!
NEW
107
            JAVAX_PERSISTENCE_UNIT_CLASS = null;
×
108
        } else {
109
            JAVAX_PERSISTENCE_UNIT_CLASS = searchTypeInClasspath("javax.persistence.PersistenceUnit");
1✔
110
        }
111
    }
1✔
112

113
    @NonNull
114
    public final Type type;
115

116
    @Nullable
117
    public final String name;
118

119
    @Nullable
120
    private final String normalizedName;
121

122
    public final boolean qualified;
123

124
    public InjectionPoint(@NonNull Type type) {
125
        this(type, null, false);
1✔
126
    }
1✔
127

128
    public InjectionPoint(@NonNull Type type, @Nullable String name) {
129
        this(type, name, false);
1✔
130
    }
1✔
131

132
    public InjectionPoint(@NonNull Type type, @Nullable String name, boolean qualified) {
1✔
133
        this.type = type;
1✔
134
        this.name = name;
1✔
135
        normalizedName = name == null ? null : convertToLegalJavaIdentifierIfNeeded(name);
1✔
136
        this.qualified = qualified;
1✔
137
    }
1✔
138

139
    public InjectionPoint(@NonNull Type type, @NonNull String name, @Nullable String qualifiedName) {
1✔
140
        this.type = type;
1✔
141
        this.name = qualifiedName == null ? name : qualifiedName;
1✔
142
        normalizedName = this.name;
1✔
143
        qualified = qualifiedName != null;
1✔
144
    }
1✔
145

146
    @NonNull
147
    public static String convertToLegalJavaIdentifierIfNeeded(@NonNull String name) {
148
        if (name.indexOf('-') < 0 && name.indexOf('.') < 0) {
1✔
149
            return name;
1✔
150
        }
151

152
        StringBuilder identifier = new StringBuilder(name);
1✔
153

154
        for (int i = name.length() - 1; i >= 0; i--) {
1✔
155
            char c = identifier.charAt(i);
1✔
156

157
            if (c == '-' || c == '.') {
1✔
158
                identifier.deleteCharAt(i);
1✔
159
                char d = identifier.charAt(i);
1✔
160
                identifier.setCharAt(i, toUpperCase(d));
1✔
161
            }
162
        }
163

164
        return identifier.toString();
1✔
165
    }
166

167
    @Override
168
    @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
169
    public boolean equals(Object other) {
170
        if (this == other) {
1!
171
            return true;
×
172
        }
173

174
        InjectionPoint otherIP = (InjectionPoint) other;
1✔
175

176
        if (type instanceof TypeVariable<?> || otherIP.type instanceof TypeVariable<?>) {
1!
177
            return false;
1✔
178
        }
179

180
        String thisName = normalizedName;
1✔
181

182
        return type.equals(otherIP.type) && (thisName == null || thisName.equals(otherIP.normalizedName));
1✔
183
    }
184

185
    @Override
186
    public int hashCode() {
187
        return 31 * type.hashCode() + (normalizedName == null ? 0 : normalizedName.hashCode());
1✔
188
    }
189

190
    boolean hasSameName(InjectionPoint otherIP) {
191
        String thisName = normalizedName;
1✔
192
        return thisName != null && thisName.equals(otherIP.normalizedName);
1✔
193
    }
194

195
    static boolean isJakartaServlet(@NonNull Class<?> aClass) {
196
        return JAKARTA_SERVLET_CLASS != null && jakarta.servlet.Servlet.class.isAssignableFrom(aClass);
1!
197
    }
198

199
    static boolean isJavaxServlet(@NonNull Class<?> aClass) {
200
        return JAVAX_SERVLET_CLASS != null && javax.servlet.Servlet.class.isAssignableFrom(aClass);
1!
201
    }
202

203
    @NonNull
204
    public static Object wrapInProviderIfNeeded(@NonNull Type type, @NonNull final Object value) {
205
        if (JAKARTA_INJECT_CLASS != null && type instanceof ParameterizedType
1!
206
                && !(value instanceof jakarta.inject.Provider)) {
207
            Type parameterizedType = ((ParameterizedType) type).getRawType();
1✔
208

209
            if (parameterizedType == jakarta.inject.Provider.class) {
1!
NEW
210
                return (jakarta.inject.Provider<Object>) () -> value;
×
211
            }
212

213
            if (JAKARTA_INSTANCE_CLASS != null && parameterizedType == jakarta.enterprise.inject.Instance.class) {
1!
214
                @SuppressWarnings("unchecked")
UNCOV
215
                List<Object> values = (List<Object>) value;
×
NEW
216
                return new ListedJakarta(values);
×
217
            }
218
        }
219

220
        if (JAVAX_INJECT_CLASS != null && type instanceof ParameterizedType
1!
221
                && !(value instanceof javax.inject.Provider)) {
222
            Type parameterizedType = ((ParameterizedType) type).getRawType();
1✔
223

224
            if (parameterizedType == javax.inject.Provider.class) {
1✔
225
                return (javax.inject.Provider<Object>) () -> value;
1✔
226
            }
227

228
            if (JAVAX_INSTANCE_CLASS != null && parameterizedType == javax.enterprise.inject.Instance.class) {
1!
229
                @SuppressWarnings("unchecked")
230
                List<Object> values = (List<Object>) value;
1✔
231
                return new ListedJavax(values);
1✔
232
            }
233
        }
234

235
        return value;
1✔
236
    }
237

238
    private static final class ListedJakarta implements jakarta.enterprise.inject.Instance<Object> {
239
        @NonNull
240
        private final List<Object> instances;
241

NEW
242
        ListedJakarta(@NonNull List<Object> instances) {
×
NEW
243
            this.instances = instances;
×
NEW
244
        }
×
245

246
        @Override
247
        public jakarta.enterprise.inject.Instance<Object> select(Annotation... annotations) {
NEW
248
            return null;
×
249
        }
250

251
        @Override
252
        public <U> jakarta.enterprise.inject.Instance<U> select(Class<U> uClass, Annotation... annotations) {
NEW
253
            return null;
×
254
        }
255

256
        @Override
257
        public <U> jakarta.enterprise.inject.Instance<U> select(jakarta.enterprise.util.TypeLiteral<U> tl,
258
                Annotation... annotations) {
NEW
259
            return null;
×
260
        }
261

262
        @Override
263
        public boolean isUnsatisfied() {
NEW
264
            return false;
×
265
        }
266

267
        @Override
268
        public boolean isAmbiguous() {
NEW
269
            return false;
×
270
        }
271

272
        @Override
273
        public void destroy(Object instance) {
NEW
274
        }
×
275

276
        @Override
277
        public Iterator<Object> iterator() {
NEW
278
            return instances.iterator();
×
279
        }
280

281
        @Override
282
        public Object get() {
NEW
283
            throw new RuntimeException("Unexpected");
×
284
        }
285

286
        @Override
287
        public Iterable<? extends jakarta.enterprise.inject.Instance.Handle<Object>> handles() {
288
            class SimpleHandle implements jakarta.enterprise.inject.Instance.Handle<Object> {
289
                private final Object instance;
290

NEW
291
                SimpleHandle(Object instance) {
×
NEW
292
                    this.instance = instance;
×
NEW
293
                }
×
294

295
                @Override
296
                public Object get() {
NEW
297
                    return instance;
×
298
                }
299

300
                @Override
301
                public void destroy() {
302
                    // No-op
NEW
303
                }
×
304

305
                @Override
306
                public void close() {
307
                    // No-op
NEW
308
                }
×
309

310
                @Override
311
                public jakarta.enterprise.inject.spi.Bean<Object> getBean() {
NEW
312
                    return null;
×
313
                }
314
            }
NEW
315
            List<SimpleHandle> handleList = new ArrayList<>();
×
NEW
316
            for (Object obj : instances) {
×
NEW
317
                handleList.add(new SimpleHandle(obj));
×
NEW
318
            }
×
NEW
319
            return handleList;
×
320
        }
321

322
        @Override
323
        public jakarta.enterprise.inject.Instance.Handle<Object> getHandle() {
NEW
324
            if (instances.isEmpty()) {
×
NEW
325
                throw new RuntimeException("No instance available");
×
326
            }
NEW
327
            return new jakarta.enterprise.inject.Instance.Handle<Object>() {
×
NEW
328
                private final Object instance = instances.get(0);
×
329

330
                @Override
331
                public Object get() {
NEW
332
                    return instance;
×
333
                }
334

335
                @Override
336
                public void destroy() {
337
                    // No-op
NEW
338
                }
×
339

340
                @Override
341
                public void close() {
342
                    // No-op
NEW
343
                }
×
344

345
                @Override
346
                public jakarta.enterprise.inject.spi.Bean<Object> getBean() {
NEW
347
                    return null;
×
348
                }
349
            };
350
        }
351
    }
352

353
    private static final class ListedJavax implements javax.enterprise.inject.Instance<Object> {
354
        @NonNull
355
        private final List<Object> instances;
356

357
        ListedJavax(@NonNull List<Object> instances) {
1✔
358
            this.instances = instances;
1✔
359
        }
1✔
360

361
        @Override
362
        public javax.enterprise.inject.Instance<Object> select(Annotation... annotations) {
363
            return null;
×
364
        }
365

366
        @Override
367
        public <U> javax.enterprise.inject.Instance<U> select(Class<U> uClass, Annotation... annotations) {
368
            return null;
×
369
        }
370

371
        @Override
372
        public <U> javax.enterprise.inject.Instance<U> select(javax.enterprise.util.TypeLiteral<U> tl,
373
                Annotation... annotations) {
UNCOV
374
            return null;
×
375
        }
376

377
        @Override
378
        public boolean isUnsatisfied() {
379
            return false;
1✔
380
        }
381

382
        @Override
383
        public boolean isAmbiguous() {
384
            return false;
1✔
385
        }
386

387
        @Override
388
        public void destroy(Object instance) {
389
        }
×
390

391
        @Override
392
        public Iterator<Object> iterator() {
393
            return instances.iterator();
1✔
394
        }
395

396
        @Override
397
        public Object get() {
398
            throw new RuntimeException("Unexpected");
×
399
        }
400
    }
401

402
    @NonNull
403
    public static KindOfInjectionPoint kindOfInjectionPoint(@NonNull AccessibleObject fieldOrConstructor) {
404
        Annotation[] annotations = fieldOrConstructor.getDeclaredAnnotations();
1✔
405

406
        if (annotations.length == 0) {
1✔
407
            return KindOfInjectionPoint.NotAnnotated;
1✔
408
        }
409

410
        if (JAKARTA_INJECT_CLASS != null && isAnnotated(annotations, jakarta.inject.Inject.class)) {
1!
NEW
411
            return KindOfInjectionPoint.Required;
×
412
        }
413

414
        if (JAVAX_INJECT_CLASS != null && isAnnotated(annotations, javax.inject.Inject.class)) {
1!
415
            return KindOfInjectionPoint.Required;
1✔
416
        }
417

418
        KindOfInjectionPoint kind = isAutowired(annotations);
1✔
419

420
        if (kind != KindOfInjectionPoint.NotAnnotated || fieldOrConstructor instanceof Constructor) {
1!
421
            return kind;
1✔
422
        }
423

424
        if (isRequiredJakarta(annotations) || isRequiredJavax(annotations)) {
1!
425
            return KindOfInjectionPoint.Required;
1✔
426
        }
427

428
        return KindOfInjectionPoint.NotAnnotated;
1✔
429
    }
430

431
    private static boolean isAnnotated(@NonNull Annotation[] declaredAnnotations,
432
            @NonNull Class<?> annotationOfInterest) {
433
        Annotation annotation = getAnnotation(declaredAnnotations, annotationOfInterest);
1✔
434
        return annotation != null;
1✔
435
    }
436

437
    @Nullable
438
    private static Annotation getAnnotation(@NonNull Annotation[] declaredAnnotations,
439
            @NonNull Class<?> annotationOfInterest) {
440
        for (Annotation declaredAnnotation : declaredAnnotations) {
1✔
441
            if (declaredAnnotation.annotationType() == annotationOfInterest) {
1✔
442
                return declaredAnnotation;
1✔
443
            }
444
        }
445

446
        return null;
1✔
447
    }
448

449
    @NonNull
450
    private static KindOfInjectionPoint isAutowired(@NonNull Annotation[] declaredAnnotations) {
451
        for (Annotation declaredAnnotation : declaredAnnotations) {
1✔
452
            Class<?> annotationType = declaredAnnotation.annotationType();
1✔
453

454
            if (annotationType.getName().endsWith(".Autowired")) {
1✔
455
                Boolean required = invokePublicIfAvailable(annotationType, declaredAnnotation, "required",
1✔
456
                        NO_PARAMETERS);
457
                return required != null && required ? KindOfInjectionPoint.Required : KindOfInjectionPoint.Optional;
1!
458
            }
459
        }
460

461
        return KindOfInjectionPoint.NotAnnotated;
1✔
462
    }
463

464
    private static boolean isRequiredJakarta(@NonNull Annotation[] annotations) {
465
        return JAKARTA_RESOURCE_CLASS != null && isAnnotated(annotations, jakarta.annotation.Resource.class)
1!
466
                || JAKARTA_EJB_CLASS != null && isAnnotated(annotations, jakarta.ejb.EJB.class)
1!
467
                || JAKARTA_PERSISTENCE_UNIT_CLASS != null
468
                        && (isAnnotated(annotations, jakarta.persistence.PersistenceContext.class)
1!
469
                                || isAnnotated(annotations, jakarta.persistence.PersistenceUnit.class));
1!
470
    }
471

472
    private static boolean isRequiredJavax(@NonNull Annotation[] annotations) {
473
        return JAVAX_RESOURCE_CLASS != null && isAnnotated(annotations, javax.annotation.Resource.class)
1!
474
                || JAVAX_EJB_CLASS != null && isAnnotated(annotations, javax.ejb.EJB.class)
1!
475
                || JAVAX_PERSISTENCE_UNIT_CLASS != null
476
                        && (isAnnotated(annotations, javax.persistence.PersistenceContext.class)
1✔
477
                                || isAnnotated(annotations, javax.persistence.PersistenceUnit.class));
1✔
478
    }
479

480
    @NonNull
481
    public static Type getTypeOfInjectionPointFromVarargsParameter(@NonNull Type parameterType) {
482
        if (parameterType instanceof Class<?>) {
1✔
483
            return ((Class<?>) parameterType).getComponentType();
1✔
484
        }
485

486
        return ((GenericArrayType) parameterType).getGenericComponentType();
1✔
487
    }
488

489
    @Nullable
490
    public static String getQualifiedName(@NonNull Annotation[] annotationsOnInjectionPoint) {
491
        for (Annotation annotation : annotationsOnInjectionPoint) {
1✔
492
            Class<?> annotationType = annotation.annotationType();
1✔
493
            String annotationName = annotationType.getName();
1✔
494

495
            if ("jakarta.annotation.Resource jakarta.ejb.EJB".contains(annotationName)
1!
496
                    || "javax.annotation.Resource javax.ejb.EJB".contains(annotationName)) {
1✔
497
                String name = readAnnotationAttribute(annotation, "name");
1✔
498

499
                if (name.isEmpty()) {
1✔
500
                    name = readAnnotationAttributeIfAvailable(annotation, "lookup"); // EJB 3.0 has no "lookup"
1✔
501
                    // attribute
502

503
                    if (name == null || name.isEmpty()) {
1!
504
                        name = readAnnotationAttribute(annotation, "mappedName");
1✔
505
                    }
506

507
                    name = name.isEmpty() ? null : getNameFromJNDILookup(name);
1✔
508
                }
509

510
                return name;
1✔
511
            }
512

513
            if ("jakarta.inject.Named".equals(annotationName) || "javax.inject.Named".equals(annotationName)
1!
514
                    || annotationName.endsWith(".Qualifier")) {
1✔
515
                return readAnnotationAttribute(annotation, "value");
1✔
516
            }
517
        }
518

519
        return null;
1✔
520
    }
521

522
    @NonNull
523
    public static String getNameFromJNDILookup(@NonNull String jndiLookup) {
524
        int p = jndiLookup.lastIndexOf('/');
1✔
525

526
        if (p >= 0) {
1✔
527
            jndiLookup = jndiLookup.substring(p + 1);
1✔
528
        }
529

530
        return jndiLookup;
1✔
531
    }
532
}
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