8282import io .quarkus .gizmo .ResultHandle ;
8383import io .quarkus .hibernate .validator .spi .AdditionalConstrainedClassBuildItem ;
8484import io .quarkus .paths .PathCollection ;
85+ import io .quarkus .runtime .BuildAnalyticsConfig ;
86+ import io .quarkus .runtime .BuilderConfig ;
87+ import io .quarkus .runtime .CommandLineRuntimeConfig ;
88+ import io .quarkus .runtime .DebugRuntimeConfig ;
8589import io .quarkus .runtime .LaunchMode ;
8690import io .quarkus .runtime .annotations .StaticInitSafe ;
8791import io .quarkus .runtime .configuration .AbstractConfigBuilder ;
9498import io .quarkus .runtime .configuration .RuntimeOverrideConfigSource ;
9599import io .quarkus .runtime .configuration .RuntimeOverrideConfigSourceBuilder ;
96100import io .quarkus .runtime .configuration .StaticInitConfigBuilder ;
101+ import io .smallrye .config .ConfigMappingLoader ;
102+ import io .smallrye .config .ConfigMappingMetadata ;
97103import io .smallrye .config .ConfigMappings .ConfigClass ;
98104import io .smallrye .config .ConfigSourceFactory ;
99105import io .smallrye .config .ConfigSourceInterceptor ;
@@ -257,15 +263,34 @@ void generateBuilders(
257263 Set <String > secretKeyHandlerFactories = discoverService (SecretKeysHandlerFactory .class , reflectiveClass );
258264 Set <String > configCustomizers = discoverService (SmallRyeConfigBuilderCustomizer .class , reflectiveClass );
259265
266+ // TODO - introduce a way to ignore mappings that are only used for documentation or to prevent warnings
267+ Set <ConfigClass > ignoreMappings = new HashSet <>();
268+ ignoreMappings .add (ConfigClass .configClass (BuildAnalyticsConfig .class , "quarkus.analytics" ));
269+ ignoreMappings .add (ConfigClass .configClass (BuilderConfig .class , "quarkus.builder" ));
270+ ignoreMappings .add (ConfigClass .configClass (CommandLineRuntimeConfig .class , "quarkus" ));
271+ ignoreMappings .add (ConfigClass .configClass (DebugRuntimeConfig .class , "quarkus.debug" ));
272+
273+ Set <ConfigClass > allMappings = new HashSet <>();
274+ allMappings .addAll (staticSafeConfigMappings (configMappings ));
275+ allMappings .addAll (runtimeConfigMappings (configMappings ));
276+ allMappings .addAll (configItem .getReadResult ().getBuildTimeRunTimeMappings ());
277+ allMappings .addAll (configItem .getReadResult ().getRunTimeMappings ());
278+ allMappings .removeAll (ignoreMappings );
279+
280+ // Shared components
281+ Map <Object , FieldDescriptor > sharedFields = generateSharedConfig (generatedClass , converters , allMappings );
282+
260283 // For Static Init Config
261284 Set <ConfigClass > staticMappings = new HashSet <>();
262285 staticMappings .addAll (staticSafeConfigMappings (configMappings ));
263286 staticMappings .addAll (configItem .getReadResult ().getBuildTimeRunTimeMappings ());
287+ staticMappings .removeAll (ignoreMappings );
264288 Set <String > staticCustomizers = new HashSet <>(staticSafeServices (configCustomizers ));
265289 staticCustomizers .add (StaticInitConfigBuilder .class .getName ());
266290
267291 generateConfigBuilder (generatedClass , reflectiveClass , CONFIG_STATIC_NAME ,
268292 combinedIndex ,
293+ sharedFields ,
269294 defaultValues ,
270295 converters ,
271296 interceptors ,
@@ -275,6 +300,7 @@ void generateBuilders(
275300 staticSafeServices (configSourceFactories ),
276301 secretKeyHandlers ,
277302 staticSafeServices (secretKeyHandlerFactories ),
303+ Set .of (),
278304 staticMappings ,
279305 staticCustomizers ,
280306 staticInitConfigBuilders .stream ().map (StaticInitConfigBuilderBuildItem ::getBuilderClassName ).collect (toSet ()));
@@ -285,11 +311,13 @@ void generateBuilders(
285311 runTimeMappings .addAll (runtimeConfigMappings (configMappings ));
286312 runTimeMappings .addAll (configItem .getReadResult ().getBuildTimeRunTimeMappings ());
287313 runTimeMappings .addAll (configItem .getReadResult ().getRunTimeMappings ());
314+ runTimeMappings .removeAll (ignoreMappings );
288315 Set <String > runtimeCustomizers = new HashSet <>(configCustomizers );
289316 runtimeCustomizers .add (RuntimeConfigBuilder .class .getName ());
290317
291318 generateConfigBuilder (generatedClass , reflectiveClass , CONFIG_RUNTIME_NAME ,
292319 combinedIndex ,
320+ sharedFields ,
293321 defaultValues ,
294322 converters ,
295323 interceptors ,
@@ -299,6 +327,7 @@ void generateBuilders(
299327 configSourceFactories ,
300328 secretKeyHandlers ,
301329 secretKeyHandlerFactories ,
330+ staticMappings ,
302331 runTimeMappings ,
303332 runtimeCustomizers ,
304333 runTimeConfigBuilders .stream ().map (RunTimeConfigBuilderBuildItem ::getBuilderClassName ).collect (toSet ()));
@@ -532,12 +561,12 @@ private static String getPathWithoutExtension(Path path) {
532561 private static final MethodDescriptor BUILDER_CUSTOMIZER = MethodDescriptor .ofMethod (SmallRyeConfigBuilderCustomizer .class ,
533562 "configBuilder" ,
534563 void .class , SmallRyeConfigBuilder .class );
535-
536- private static final MethodDescriptor WITH_DEFAULT = MethodDescriptor .ofMethod (AbstractConfigBuilder .class ,
537- "withDefaultValue" ,
538- void .class , SmallRyeConfigBuilder .class , String .class , String .class );
564+ private static final MethodDescriptor WITH_DEFAULTS = MethodDescriptor .ofMethod (AbstractConfigBuilder .class ,
565+ "withDefaultValues" ,
566+ void .class , SmallRyeConfigBuilder .class , Map .class );
539567 private static final MethodDescriptor WITH_CONVERTER = MethodDescriptor .ofMethod (AbstractConfigBuilder .class ,
540- "withConverter" , void .class , SmallRyeConfigBuilder .class , String .class , int .class , Converter .class );
568+ "withConverter" ,
569+ void .class , SmallRyeConfigBuilder .class , String .class , int .class , Converter .class );
541570 private static final MethodDescriptor WITH_INTERCEPTOR = MethodDescriptor .ofMethod (AbstractConfigBuilder .class ,
542571 "withInterceptor" ,
543572 void .class , SmallRyeConfigBuilder .class , ConfigSourceInterceptor .class );
@@ -554,27 +583,86 @@ private static String getPathWithoutExtension(Path path) {
554583 "withSource" ,
555584 void .class , SmallRyeConfigBuilder .class , ConfigSourceFactory .class );
556585 private static final MethodDescriptor WITH_SECRET_HANDLER = MethodDescriptor .ofMethod (AbstractConfigBuilder .class ,
557- "withSecretKeyHandler" , void .class , SmallRyeConfigBuilder .class , SecretKeysHandler .class );
586+ "withSecretKeyHandler" ,
587+ void .class , SmallRyeConfigBuilder .class , SecretKeysHandler .class );
558588 private static final MethodDescriptor WITH_SECRET_HANDLER_FACTORY = MethodDescriptor .ofMethod (AbstractConfigBuilder .class ,
559- "withSecretKeyHandler" , void .class , SmallRyeConfigBuilder .class , SecretKeysHandlerFactory .class );
589+ "withSecretKeyHandler" ,
590+ void .class , SmallRyeConfigBuilder .class , SecretKeysHandlerFactory .class );
560591 private static final MethodDescriptor WITH_MAPPING = MethodDescriptor .ofMethod (AbstractConfigBuilder .class ,
561592 "withMapping" ,
562- void .class , SmallRyeConfigBuilder .class , String .class , String .class );
593+ void .class , SmallRyeConfigBuilder .class , ConfigClass .class );
594+ private static final MethodDescriptor WITH_MAPPING_INSTANCE = MethodDescriptor .ofMethod (AbstractConfigBuilder .class ,
595+ "withMappingInstance" ,
596+ void .class , SmallRyeConfigBuilder .class , ConfigClass .class );
563597 private static final MethodDescriptor WITH_CUSTOMIZER = MethodDescriptor .ofMethod (AbstractConfigBuilder .class ,
564598 "withCustomizer" ,
565599 void .class , SmallRyeConfigBuilder .class , SmallRyeConfigBuilderCustomizer .class );
566600 private static final MethodDescriptor WITH_BUILDER = MethodDescriptor .ofMethod (AbstractConfigBuilder .class ,
567601 "withBuilder" ,
568602 void .class , SmallRyeConfigBuilder .class , ConfigBuilder .class );
603+ private static final MethodDescriptor CONFIG_CLASS = MethodDescriptor .ofMethod (AbstractConfigBuilder .class ,
604+ "configClass" ,
605+ ConfigClass .class , String .class , String .class );
606+ private static final MethodDescriptor ENSURE_LOADED = MethodDescriptor .ofMethod (AbstractConfigBuilder .class ,
607+ "ensureLoaded" ,
608+ void .class , String .class );
569609
570610 private static final DotName CONVERTER_NAME = DotName .createSimple (Converter .class .getName ());
571611 private static final DotName PRIORITY_NAME = DotName .createSimple (Priority .class .getName ());
572612
613+ private static Map <Object , FieldDescriptor > generateSharedConfig (
614+ BuildProducer <GeneratedClassBuildItem > generatedClass ,
615+ Set <String > converters ,
616+ Set <ConfigClass > mappings ) {
617+
618+ Map <Object , FieldDescriptor > fields = new HashMap <>();
619+ try (ClassCreator classCreator = ClassCreator .builder ()
620+ .classOutput (new GeneratedClassGizmoAdaptor (generatedClass , true ))
621+ .className ("io.quarkus.runtime.generated.SharedConfig" )
622+ .superClass (AbstractConfigBuilder .class )
623+ .setFinal (true )
624+ .build ()) {
625+
626+ MethodCreator clinit = classCreator .getMethodCreator ("<clinit>" , void .class );
627+ clinit .setModifiers (Opcodes .ACC_STATIC );
628+
629+ int converterIndex = 0 ;
630+ for (String converter : converters ) {
631+ String fieldName = "conv$" + converterIndex ++;
632+ FieldDescriptor converterField = classCreator .getFieldCreator (fieldName , Converter .class )
633+ .setModifiers (Opcodes .ACC_STATIC ).getFieldDescriptor ();
634+ clinit .writeStaticField (converterField , clinit .newInstance (MethodDescriptor .ofConstructor (converter )));
635+ fields .put (converter , converterField );
636+ }
637+
638+ int mappingIndex = 0 ;
639+ for (ConfigClass mapping : mappings ) {
640+ FieldDescriptor mappingField = classCreator .getFieldCreator ("mapping$" + mappingIndex ++, ConfigClass .class )
641+ .setModifiers (Opcodes .ACC_STATIC ).getFieldDescriptor ();
642+ clinit .writeStaticField (mappingField , clinit .invokeStaticMethod (CONFIG_CLASS ,
643+ clinit .load (mapping .getType ().getName ()), clinit .load (mapping .getPrefix ())));
644+
645+ List <ConfigMappingMetadata > configMappingsMetadata = ConfigMappingLoader
646+ .getConfigMappingsMetadata (mapping .getType ());
647+ for (ConfigMappingMetadata configMappingMetadata : configMappingsMetadata ) {
648+ clinit .invokeStaticMethod (ENSURE_LOADED , clinit .load (configMappingMetadata .getInterfaceType ().getName ()));
649+ }
650+
651+ fields .put (mapping , mappingField );
652+ }
653+
654+ clinit .returnVoid ();
655+ }
656+
657+ return fields ;
658+ }
659+
573660 private static void generateConfigBuilder (
574661 BuildProducer <GeneratedClassBuildItem > generatedClass ,
575662 BuildProducer <ReflectiveClassBuildItem > reflectiveClass ,
576663 String className ,
577664 CombinedIndexBuildItem combinedIndex ,
665+ Map <Object , FieldDescriptor > sharedFields ,
578666 Map <String , String > defaultValues ,
579667 Set <String > converters ,
580668 Set <String > interceptors ,
@@ -584,6 +672,7 @@ private static void generateConfigBuilder(
584672 Set <String > configSourceFactories ,
585673 Set <String > secretKeyHandlers ,
586674 Set <String > secretKeyHandlerFactories ,
675+ Set <ConfigClass > mappingsInstances ,
587676 Set <ConfigClass > mappings ,
588677 Set <String > configCustomizers ,
589678 Set <String > configBuilders ) {
@@ -597,23 +686,33 @@ private static void generateConfigBuilder(
597686 .setFinal (true )
598687 .build ()) {
599688
689+ MethodCreator clinit = classCreator .getMethodCreator ("<clinit>" , void .class );
690+ clinit .setModifiers (Opcodes .ACC_STATIC );
691+
600692 MethodCreator method = classCreator .getMethodCreator (BUILDER_CUSTOMIZER );
601693 ResultHandle configBuilder = method .getMethodParam (0 );
602694
695+ FieldDescriptor defaultsField = classCreator .getFieldCreator ("defaults" , Map .class ).setModifiers (Opcodes .ACC_STATIC )
696+ .getFieldDescriptor ();
697+ clinit .writeStaticField (defaultsField , clinit .newInstance (MethodDescriptor .ofConstructor (HashMap .class , int .class ),
698+ clinit .load ((int ) ((float ) defaultValues .size () / 0.75f + 1.0f ))));
699+ MethodDescriptor put = MethodDescriptor .ofMethod (HashMap .class , "put" , Object .class , Object .class , Object .class );
603700 for (Map .Entry <String , String > entry : defaultValues .entrySet ()) {
604- method . invokeStaticMethod ( WITH_DEFAULT , configBuilder , method .load (entry .getKey ()),
605- method .load (entry .getValue ()));
701+ clinit . invokeVirtualMethod ( put , clinit . readStaticField ( defaultsField ), clinit .load (entry .getKey ()),
702+ clinit .load (entry .getValue ()));
606703 }
704+ method .invokeStaticMethod (WITH_DEFAULTS , configBuilder , method .readStaticField (defaultsField ));
607705
608706 for (String converter : converters ) {
609707 ClassInfo converterClass = combinedIndex .getComputingIndex ().getClassByName (converter );
610708 Type type = getConverterType (converterClass , combinedIndex );
611709 AnnotationInstance priorityAnnotation = converterClass .annotation (PRIORITY_NAME );
612710 int priority = priorityAnnotation != null ? priorityAnnotation .value ().asInt () : 100 ;
711+
613712 method .invokeStaticMethod (WITH_CONVERTER , configBuilder ,
614713 method .load (type .name ().toString ()),
615714 method .load (priority ),
616- method .newInstance ( MethodDescriptor . ofConstructor (converter )));
715+ method .readStaticField ( sharedFields . get (converter )));
617716 }
618717
619718 for (String interceptor : interceptors ) {
@@ -651,11 +750,17 @@ private static void generateConfigBuilder(
651750 method .newInstance (MethodDescriptor .ofConstructor (secretKeyHandlerFactory )));
652751 }
653752
753+ for (ConfigClass mappingInstance : mappingsInstances ) {
754+ method .invokeStaticMethod (WITH_MAPPING_INSTANCE , configBuilder ,
755+ method .readStaticField (sharedFields .get (mappingInstance )));
756+ }
757+
758+ mappings .removeAll (mappingsInstances );
654759 for (ConfigClass mapping : mappings ) {
655- method .invokeStaticMethod (WITH_MAPPING , configBuilder , method .load (mapping .getKlass ().getName ()),
656- method .load (mapping .getPrefix ()));
760+ method .invokeStaticMethod (WITH_MAPPING , configBuilder , method .readStaticField (sharedFields .get (mapping )));
657761 }
658762
763+ clinit .returnVoid ();
659764 method .returnVoid ();
660765 }
661766
0 commit comments