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

hazendaz / jmockit1 / 496

15 Nov 2025 05:33PM UTC coverage: 72.192% (-0.008%) from 72.2%
496

push

github

web-flow
Merge pull request #412 from hazendaz/renovate/major-spring-core

Update spring core to v7 (major)

5677 of 8360 branches covered (67.91%)

Branch coverage included in aggregate %.

11922 of 16018 relevant lines covered (74.43%)

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
 * MIT License
3
 * Copyright (c) 2006-2025 JMockit developers
4
 * See LICENSE file for full license text.
5
 */
6
package mockit.internal.injection;
7

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

114
    @NonNull
115
    public final Type type;
116

117
    @Nullable
118
    public final String name;
119

120
    @Nullable
121
    private final String normalizedName;
122

123
    public final boolean qualified;
124

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

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

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

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

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

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

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

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

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

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

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

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

181
        String thisName = normalizedName;
1✔
182

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

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

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

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

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

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

210
            if (parameterizedType == jakarta.inject.Provider.class) {
1✔
211
                return (jakarta.inject.Provider<Object>) () -> value;
1✔
212
            }
213

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

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

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

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

236
        return value;
1✔
237
    }
238

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

243
        ListedJakarta(@NonNull List<Object> instances) {
1✔
244
            this.instances = instances;
1✔
245
        }
1✔
246

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

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

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

263
        @Override
264
        public boolean isUnsatisfied() {
265
            return false;
1✔
266
        }
267

268
        @Override
269
        public boolean isAmbiguous() {
270
            return false;
1✔
271
        }
272

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

277
        @Override
278
        public Iterator<Object> iterator() {
279
            return instances.iterator();
1✔
280
        }
281

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

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

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

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

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

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

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

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

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

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

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

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

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

358
        ListedJavax(@NonNull List<Object> instances) {
×
359
            this.instances = instances;
×
360
        }
×
361

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

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

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

378
        @Override
379
        public boolean isUnsatisfied() {
380
            return false;
×
381
        }
382

383
        @Override
384
        public boolean isAmbiguous() {
385
            return false;
×
386
        }
387

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

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

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

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

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

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

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

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

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

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

429
        return KindOfInjectionPoint.NotAnnotated;
1✔
430
    }
431

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

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

447
        return null;
1✔
448
    }
449

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

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

462
        return KindOfInjectionPoint.NotAnnotated;
1✔
463
    }
464

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

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

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

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

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

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

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

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

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

511
                return name;
1✔
512
            }
513

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

520
        return null;
1✔
521
    }
522

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

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

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