Skip to content

Commit 9d8705d

Browse files
committed
Ignore GraalVM features in HibernateValidatorProcessor
Fixes #47033
1 parent 4684bd6 commit 9d8705d

File tree

1 file changed

+56
-12
lines changed

1 file changed

+56
-12
lines changed

extensions/hibernate-validator/deployment/src/main/java/io/quarkus/hibernate/validator/deployment/HibernateValidatorProcessor.java

+56-12
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ class HibernateValidatorProcessor {
154154

155155
private static final DotName REPEATABLE = DotName.createSimple(Repeatable.class.getName());
156156

157+
private static final DotName GRAALVM_FEATURE = DotName.createSimple("org.graalvm.nativeimage.hosted.Feature");
158+
157159
private static final Pattern BUILT_IN_CONSTRAINT_REPEATABLE_CONTAINER_PATTERN = Pattern.compile("\\$List$");
158160

159161
@BuildStep
@@ -498,12 +500,12 @@ public void build(
498500

499501
for (AnnotationInstance annotation : annotationInstances) {
500502
if (annotation.target().kind() == AnnotationTarget.Kind.FIELD) {
501-
contributeClass(classNamesToBeValidated, indexView, annotation.target().asField().declaringClass().name());
503+
contributeClass(classNamesToBeValidated, indexView, annotation.target().asField().declaringClass());
502504
reflectiveFields.produce(new ReflectiveFieldBuildItem(getClass().getName(), annotation.target().asField()));
503505
contributeClassMarkedForCascadingValidation(classNamesToBeValidated, indexView, consideredAnnotation,
504506
annotation.target().asField().type());
505507
} else if (annotation.target().kind() == AnnotationTarget.Kind.METHOD) {
506-
contributeClass(classNamesToBeValidated, indexView, annotation.target().asMethod().declaringClass().name());
508+
contributeClass(classNamesToBeValidated, indexView, annotation.target().asMethod().declaringClass());
507509
// we need to register the method for reflection as it could be a getter
508510
reflectiveMethods
509511
.produce(new ReflectiveMethodBuildItem(getClass().getName(), annotation.target().asMethod()));
@@ -513,7 +515,7 @@ public void build(
513515
annotation.target().asMethod());
514516
} else if (annotation.target().kind() == AnnotationTarget.Kind.METHOD_PARAMETER) {
515517
contributeClass(classNamesToBeValidated, indexView,
516-
annotation.target().asMethodParameter().method().declaringClass().name());
518+
annotation.target().asMethodParameter().method().declaringClass());
517519
// a getter does not have parameters so it's a pure method: no need for reflection in this case
518520
contributeClassMarkedForCascadingValidation(classNamesToBeValidated, indexView, consideredAnnotation,
519521
// FIXME this won't work in the case of synthetic parameters
@@ -522,21 +524,21 @@ public void build(
522524
contributeMethodsWithInheritedValidation(methodsWithInheritedValidation, indexView,
523525
annotation.target().asMethodParameter().method());
524526
} else if (annotation.target().kind() == AnnotationTarget.Kind.CLASS) {
525-
contributeClass(classNamesToBeValidated, indexView, annotation.target().asClass().name());
527+
contributeClass(classNamesToBeValidated, indexView, annotation.target().asClass());
526528
// no need for reflection in the case of a class level constraint
527529
} else if (annotation.target().kind() == AnnotationTarget.Kind.TYPE) {
528530
// container element constraints
529531
AnnotationTarget enclosingTarget = annotation.target().asType().enclosingTarget();
530532
if (enclosingTarget.kind() == AnnotationTarget.Kind.FIELD) {
531-
contributeClass(classNamesToBeValidated, indexView, enclosingTarget.asField().declaringClass().name());
533+
contributeClass(classNamesToBeValidated, indexView, enclosingTarget.asField().declaringClass());
532534
reflectiveFields.produce(new ReflectiveFieldBuildItem(getClass().getName(), enclosingTarget.asField()));
533535
if (annotation.target().asType().target() != null) {
534536
contributeClassMarkedForCascadingValidation(classNamesToBeValidated, indexView,
535537
consideredAnnotation,
536538
annotation.target().asType().target());
537539
}
538540
} else if (enclosingTarget.kind() == AnnotationTarget.Kind.METHOD) {
539-
contributeClass(classNamesToBeValidated, indexView, enclosingTarget.asMethod().declaringClass().name());
541+
contributeClass(classNamesToBeValidated, indexView, enclosingTarget.asMethod().declaringClass());
540542
reflectiveMethods
541543
.produce(new ReflectiveMethodBuildItem(getClass().getName(), enclosingTarget.asMethod()));
542544
if (annotation.target().asType().target() != null) {
@@ -701,33 +703,72 @@ private static void contributeBuiltinConstraints(Set<String> builtinConstraints,
701703
}
702704
}
703705

704-
private static void contributeClass(Set<DotName> classNamesCollector, IndexView indexView, DotName className) {
705-
classNamesCollector.add(className);
706+
private static void contributeClass(Set<DotName> classNamesCollector, IndexView indexView, ClassInfo classInfo) {
707+
if (isInGraalVMFeature(indexView, classInfo)) {
708+
return;
709+
}
706710

707-
if (DotNames.OBJECT.equals(className)) {
711+
classNamesCollector.add(classInfo.name());
712+
713+
if (DotNames.OBJECT.equals(classInfo.name())) {
708714
return;
709715
}
710716

711-
for (ClassInfo subclass : indexView.getAllKnownSubclasses(className)) {
717+
for (ClassInfo subclass : indexView.getAllKnownSubclasses(classInfo.name())) {
712718
if (Modifier.isAbstract(subclass.flags())) {
713719
// we can avoid adding the abstract classes here: either they are parent classes
714720
// and they will be dealt with by Hibernate Validator or they are child classes
715721
// without any proper implementation and we can ignore them.
716722
continue;
717723
}
724+
if (isInGraalVMFeature(indexView, subclass)) {
725+
return;
726+
}
718727
classNamesCollector.add(subclass.name());
719728
}
720-
for (ClassInfo implementor : indexView.getAllKnownImplementors(className)) {
729+
for (ClassInfo implementor : indexView.getAllKnownImplementors(classInfo.name())) {
721730
if (Modifier.isAbstract(implementor.flags())) {
722731
// we can avoid adding the abstract classes here: either they are parent classes
723732
// and they will be dealt with by Hibernate Validator or they are child classes
724733
// without any proper implementation and we can ignore them.
725734
continue;
726735
}
736+
if (isInGraalVMFeature(indexView, implementor)) {
737+
continue;
738+
}
727739
classNamesCollector.add(implementor.name());
728740
}
729741
}
730742

743+
private static boolean isInGraalVMFeature(IndexView indexView, ClassInfo classInfo) {
744+
if (classInfo.interfaceNames().contains(GRAALVM_FEATURE)) {
745+
return true;
746+
}
747+
748+
DotName hostingClassName;
749+
switch (classInfo.nestingType()) {
750+
case TOP_LEVEL:
751+
return false;
752+
case INNER:
753+
case LOCAL:
754+
hostingClassName = DotName.createSimple(classInfo.simpleName());
755+
break;
756+
case ANONYMOUS:
757+
// TODO: this doesn't work atm, Jandex will need some adjustments
758+
hostingClassName = classInfo.enclosingMethod().enclosingClass();
759+
break;
760+
default:
761+
return false;
762+
}
763+
764+
ClassInfo hostingClass = indexView.getClassByName(hostingClassName);
765+
if (hostingClass == null) {
766+
return false;
767+
}
768+
769+
return isInGraalVMFeature(indexView, hostingClass);
770+
}
771+
731772
private static void contributeClassMarkedForCascadingValidation(Set<DotName> classNamesCollector,
732773
IndexView indexView, DotName consideredAnnotation, Type type) {
733774
if (VALID != consideredAnnotation) {
@@ -736,7 +777,10 @@ private static void contributeClassMarkedForCascadingValidation(Set<DotName> cla
736777

737778
DotName className = getClassName(type);
738779
if (className != null) {
739-
contributeClass(classNamesCollector, indexView, className);
780+
ClassInfo classInfo = indexView.getClassByName(className);
781+
if (classInfo != null) {
782+
contributeClass(classNamesCollector, indexView, classInfo);
783+
}
740784
}
741785
}
742786

0 commit comments

Comments
 (0)