From 2c223d8519ae8a04ad4758b23059acbb6a3e94ea Mon Sep 17 00:00:00 2001 From: Roberto Cortez Date: Wed, 4 Dec 2024 17:56:29 +0000 Subject: [PATCH] Avoid Converters annotations introspection at runtime --- .../steps/ConfigGenerationBuildStep.java | 51 ++++++++++++++++--- .../configuration/AbstractConfigBuilder.java | 7 ++- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java index 2a9ce52ff6a437..545f9ead50601d 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java @@ -27,12 +27,19 @@ import java.util.Optional; import java.util.Set; +import jakarta.annotation.Priority; + import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; import org.eclipse.microprofile.config.ConfigValue; import org.eclipse.microprofile.config.spi.ConfigSource; import org.eclipse.microprofile.config.spi.ConfigSourceProvider; import org.eclipse.microprofile.config.spi.Converter; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.ParameterizedType; +import org.jboss.jandex.Type; import org.objectweb.asm.Opcodes; import io.quarkus.bootstrap.classloading.QuarkusClassLoader; @@ -200,6 +207,7 @@ void generateMappings( @BuildStep void generateBuilders( ConfigurationBuildItem configItem, + CombinedIndexBuildItem combinedIndex, List configMappings, List runTimeDefaults, List staticInitConfigBuilders, @@ -246,6 +254,7 @@ void generateBuilders( staticCustomizers.add(StaticInitConfigBuilder.class.getName()); generateConfigBuilder(generatedClass, reflectiveClass, CONFIG_STATIC_NAME, + combinedIndex, defaultValues, converters, interceptors, @@ -269,6 +278,7 @@ void generateBuilders( runtimeCustomizers.add(RuntimeConfigBuilder.class.getName()); generateConfigBuilder(generatedClass, reflectiveClass, CONFIG_RUNTIME_NAME, + combinedIndex, defaultValues, converters, interceptors, @@ -520,7 +530,7 @@ private static String getPathWithoutExtension(Path path) { "withDefaultValue", void.class, SmallRyeConfigBuilder.class, String.class, String.class); private static final MethodDescriptor WITH_CONVERTER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, - "withConverter", void.class, SmallRyeConfigBuilder.class, Converter.class); + "withConverter", void.class, SmallRyeConfigBuilder.class, Class.class, int.class, Converter.class); private static final MethodDescriptor WITH_INTERCEPTOR = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, "withInterceptor", void.class, SmallRyeConfigBuilder.class, ConfigSourceInterceptor.class); @@ -549,17 +559,15 @@ private static String getPathWithoutExtension(Path path) { private static final MethodDescriptor WITH_BUILDER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class, "withBuilder", void.class, SmallRyeConfigBuilder.class, ConfigBuilder.class); - private static final MethodDescriptor WITH_NAMES = MethodDescriptor.ofMethod(SmallRyeConfigBuilder.class, - "withMappingNames", - SmallRyeConfigBuilder.class, Map.class); - private static final MethodDescriptor WITH_KEYS = MethodDescriptor.ofMethod(SmallRyeConfigBuilder.class, - "withMappingKeys", - SmallRyeConfigBuilder.class, Set.class); + + private static final DotName CONVERTER_NAME = DotName.createSimple(Converter.class.getName()); + private static final DotName PRIORITY_NAME = DotName.createSimple(Priority.class.getName()); private static void generateConfigBuilder( BuildProducer generatedClass, BuildProducer reflectiveClass, String className, + CombinedIndexBuildItem combinedIndex, Map defaultValues, Set converters, Set interceptors, @@ -591,7 +599,13 @@ private static void generateConfigBuilder( } for (String converter : converters) { + ClassInfo converterClass = combinedIndex.getComputingIndex().getClassByName(converter); + Type type = getConverterType(converterClass, combinedIndex); + AnnotationInstance priorityAnnotation = converterClass.annotation(PRIORITY_NAME); + int priority = priorityAnnotation != null ? priorityAnnotation.value().asInt() : 100; method.invokeStaticMethod(WITH_CONVERTER, configBuilder, + method.loadClass(combinedIndex.getComputingIndex().getClassByName(type.name())), + method.load(priority), method.newInstance(MethodDescriptor.ofConstructor(converter))); } @@ -716,4 +730,27 @@ private static Set runtimeConfigMappings(List arguments = parameterizedType.arguments(); + if (arguments.size() != 1) { + throw new IllegalArgumentException( + "Converter " + converter.name() + " must be parameterized with a single type"); + } + return arguments.get(0); + } + } + } + + return getConverterType(combinedIndex.getComputingIndex().getClassByName(converter.superName()), combinedIndex); + } } diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/AbstractConfigBuilder.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/AbstractConfigBuilder.java index 84f9336c4ad61d..1e36e367e1868c 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/AbstractConfigBuilder.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/AbstractConfigBuilder.java @@ -21,10 +21,9 @@ protected static void withDefaultValue(SmallRyeConfigBuilder builder, String nam builder.withDefaultValue(name, value); } - // TODO - radcortez - Can be improved by avoiding introspection work in the Converter class. - // Not a big issue, because registering Converters via ServiceLoader is not a common case - protected static void withConverter(SmallRyeConfigBuilder builder, Converter converter) { - builder.withConverters(new Converter[] { converter }); + protected static void withConverter(SmallRyeConfigBuilder builder, Class type, int priority, + Converter converter) { + builder.withConverter(type, priority, converter); } protected static void withInterceptor(SmallRyeConfigBuilder builder, ConfigSourceInterceptor interceptor) {