diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index 186b103e3e18c..f23973fc842db 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -51,14 +51,14 @@
3.10.1
4.1.0
4.0.0
- 4.0.2
+ 4.0.3
2.11.0
- 6.6.1
- 4.6.0
+ 6.6.2
+ 4.6.1
2.1.2
1.0.13
3.0.1
- 3.15.0
+ 3.16.0
4.25.0
2.7.0
2.1.3
@@ -110,12 +110,12 @@
2.6.0.Final
2.2.1.Final
3.8.0.Final
- 4.5.10
+ 4.5.11
4.5.14
4.4.16
4.1.5
9.2.1
- 2.3.2
+ 2.5.0
2.3.230
42.7.4
@@ -129,10 +129,10 @@
1.2.6
2.2
5.10.5
- 15.0.10.Final
+ 15.0.11.Final
5.0.12.Final
3.1.8
- 4.1.111.Final
+ 4.1.115.Final
1.16.0
1.0.4
3.6.1.Final
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/builditem/NativeMonitoringBuildItem.java b/core/deployment/src/main/java/io/quarkus/deployment/builditem/NativeMonitoringBuildItem.java
new file mode 100644
index 0000000000000..a137322ab5ac5
--- /dev/null
+++ b/core/deployment/src/main/java/io/quarkus/deployment/builditem/NativeMonitoringBuildItem.java
@@ -0,0 +1,20 @@
+package io.quarkus.deployment.builditem;
+
+import io.quarkus.builder.item.MultiBuildItem;
+import io.quarkus.deployment.pkg.NativeConfig;
+
+/**
+ * A build item that indicates whether native monitoring is enabled and which option from {@link NativeConfig.MonitoringOption}.
+ * To be used in the native image generation.
+ */
+public final class NativeMonitoringBuildItem extends MultiBuildItem {
+ private final NativeConfig.MonitoringOption option;
+
+ public NativeMonitoringBuildItem(NativeConfig.MonitoringOption option) {
+ this.option = option;
+ }
+
+ public NativeConfig.MonitoringOption getOption() {
+ return this.option;
+ }
+}
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/ReflectiveHierarchyBuildItem.java b/core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/ReflectiveHierarchyBuildItem.java
index 54b7c35d01ffe..7e3f44d2eaa82 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/ReflectiveHierarchyBuildItem.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/ReflectiveHierarchyBuildItem.java
@@ -24,6 +24,7 @@
* register the following:
*
* - Superclasses
+ * - Subclasses
* - Component types of collections
* - Types used in bean properties (if method reflection is enabled)
* - Field types (if field reflection is enabled)
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java
index 0903a5b88b568..b160e70246a94 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java
@@ -80,9 +80,11 @@
import io.smallrye.config.EnvConfigSource;
import io.smallrye.config.ProfileConfigSourceInterceptor;
import io.smallrye.config.PropertiesConfigSource;
+import io.smallrye.config.PropertyName;
import io.smallrye.config.SecretKeys;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SmallRyeConfigBuilder;
+import io.smallrye.config.SmallRyeConfigBuilderCustomizer;
import io.smallrye.config.SysPropConfigSource;
import io.smallrye.config.common.AbstractConfigSource;
@@ -626,22 +628,19 @@ ReadResult run() {
objectsByClass.put(mapping.getKlass(), config.getConfigMapping(mapping.getKlass(), mapping.getPrefix()));
}
- // Build Time Values Recording
- for (ConfigClass mapping : buildTimeMappings) {
- Set mappedProperties = ConfigMappings.mappedProperties(mapping, allProperties);
- for (String property : mappedProperties) {
+ Set buildTimeNames = getMappingsNames(buildTimeMappings);
+ Set buildTimeRunTimeNames = getMappingsNames(buildTimeRunTimeMappings);
+ Set runTimeNames = getMappingsNames(runTimeMappings);
+ for (String property : allProperties) {
+ PropertyName name = new PropertyName(property);
+ if (buildTimeNames.contains(name)) {
unknownBuildProperties.remove(property);
ConfigValue value = config.getConfigValue(property);
if (value.getRawValue() != null) {
allBuildTimeValues.put(value.getNameProfiled(), value.getRawValue());
}
}
- }
-
- // Build Time and Run Time Values Recording
- for (ConfigClass mapping : buildTimeRunTimeMappings) {
- Set mappedProperties = ConfigMappings.mappedProperties(mapping, allProperties);
- for (String property : mappedProperties) {
+ if (buildTimeRunTimeNames.contains(name)) {
unknownBuildProperties.remove(property);
ConfigValue value = config.getConfigValue(property);
if (value.getRawValue() != null) {
@@ -649,12 +648,7 @@ ReadResult run() {
buildTimeRunTimeValues.put(value.getNameProfiled(), value.getRawValue());
}
}
- }
-
- // Run Time Values Recording
- for (ConfigClass mapping : runTimeMappings) {
- Set mappedProperties = ConfigMappings.mappedProperties(mapping, allProperties);
- for (String property : mappedProperties) {
+ if (runTimeNames.contains(name)) {
unknownBuildProperties.remove(property);
ConfigValue value = runtimeConfig.getConfigValue(property);
if (value.getRawValue() != null) {
@@ -1119,6 +1113,17 @@ private SmallRyeConfig getConfigForRuntimeRecording() {
builder.getProfiles().add("");
builder.getSources().clear();
builder.getSourceProviders().clear();
+ builder.withCustomizers(new SmallRyeConfigBuilderCustomizer() {
+ @Override
+ public void configBuilder(final SmallRyeConfigBuilder builder) {
+ builder.getMappingsBuilder().getMappings().clear();
+ }
+
+ @Override
+ public int priority() {
+ return Integer.MAX_VALUE;
+ }
+ });
builder.setAddDefaultSources(false)
// Customizers may duplicate sources, but not much we can do about it, we need to run them
.addDiscoveredCustomizers()
@@ -1216,6 +1221,14 @@ private static void getDefaults(
patternMap.getChild(childName));
}
}
+
+ private static Set getMappingsNames(final List configMappings) {
+ Set names = new HashSet<>();
+ for (ConfigClass configMapping : configMappings) {
+ names.addAll(ConfigMappings.getProperties(configMapping).keySet());
+ }
+ return PropertiesUtil.toPropertyNames(names);
+ }
}
public static final class ReadResult {
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java
index e82e137f8dd01..0d8e72863855b 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java
@@ -66,7 +66,7 @@
import io.smallrye.config.ConfigMappings;
import io.smallrye.config.ConfigMappings.ConfigClass;
import io.smallrye.config.Converters;
-import io.smallrye.config.KeyMap;
+import io.smallrye.config.PropertyName;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SmallRyeConfigBuilder;
@@ -86,10 +86,13 @@ public final class RunTimeConfigurationGenerator {
public static final MethodDescriptor REINIT = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "reinit",
void.class);
public static final MethodDescriptor C_READ_CONFIG = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "readConfig", void.class);
+
+ static final FieldDescriptor C_MAPPED_PROPERTIES = FieldDescriptor.of(CONFIG_CLASS_NAME, "mappedProperties", Set.class);
+ static final MethodDescriptor C_GENERATE_MAPPED_PROPERTIES = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME,
+ "generateMappedProperties", Set.class);
+ static final MethodDescriptor PN_NEW = MethodDescriptor.ofConstructor(PropertyName.class, String.class);
static final FieldDescriptor C_UNKNOWN = FieldDescriptor.of(CONFIG_CLASS_NAME, "unknown", Set.class);
static final FieldDescriptor C_UNKNOWN_RUNTIME = FieldDescriptor.of(CONFIG_CLASS_NAME, "unknownRuntime", Set.class);
- static final MethodDescriptor C_MAPPED_PROPERTIES = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "mappedProperties",
- KeyMap.class);
static final MethodDescriptor CD_INVALID_VALUE = MethodDescriptor.ofMethod(ConfigDiagnostic.class, "invalidValue",
void.class, String.class, IllegalArgumentException.class);
@@ -177,7 +180,6 @@ public final class RunTimeConfigurationGenerator {
Object.class, String.class, Converter.class);
static final MethodDescriptor SRCB_NEW = MethodDescriptor.ofConstructor(SmallRyeConfigBuilder.class);
-
static final MethodDescriptor SRCB_WITH_CONVERTER = MethodDescriptor.ofMethod(SmallRyeConfigBuilder.class,
"withConverter", ConfigBuilder.class, Class.class, int.class, Converter.class);
static final MethodDescriptor SRCB_WITH_CUSTOMIZER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
@@ -185,15 +187,14 @@ public final class RunTimeConfigurationGenerator {
static final MethodDescriptor SRCB_BUILD = MethodDescriptor.ofMethod(SmallRyeConfigBuilder.class, "build",
SmallRyeConfig.class);
- static final MethodDescriptor PU_FILTER_PROPERTIES_IN_ROOTS = MethodDescriptor.ofMethod(PropertiesUtil.class,
- "filterPropertiesInRoots", Iterable.class, Iterable.class, Set.class);
-
static final MethodDescriptor PU_IS_PROPERTY_QUARKUS_COMPOUND_NAME = MethodDescriptor.ofMethod(PropertiesUtil.class,
"isPropertyQuarkusCompoundName", boolean.class, NameIterator.class);
- static final MethodDescriptor PU_FILTER_UNKNOWN = MethodDescriptor.ofMethod(PropertiesUtil.class, "filterUnknown",
- void.class, Set.class, KeyMap.class);
+ static final MethodDescriptor PU_IS_PROPERTY_IN_ROOTS = MethodDescriptor.ofMethod(PropertiesUtil.class, "isPropertyInRoots",
+ boolean.class, String.class, Set.class);
static final MethodDescriptor HS_NEW = MethodDescriptor.ofConstructor(HashSet.class);
static final MethodDescriptor HS_ADD = MethodDescriptor.ofMethod(HashSet.class, "add", boolean.class, Object.class);
+ static final MethodDescriptor HS_CONTAINS = MethodDescriptor.ofMethod(HashSet.class, "contains", boolean.class,
+ Object.class);
// todo: more space-efficient sorted map impl
static final MethodDescriptor TM_NEW = MethodDescriptor.ofConstructor(TreeMap.class);
@@ -261,8 +262,8 @@ public static final class GenerateOperation implements AutoCloseable {
roots = Assert.checkNotNullParam("builder.roots", builder.getBuildTimeReadResult().getAllRoots());
additionalTypes = Assert.checkNotNullParam("additionalTypes", builder.getAdditionalTypes());
cc = ClassCreator.builder().classOutput(classOutput).className(CONFIG_CLASS_NAME).setFinal(true).build();
+ generateMappedProperties();
generateEmptyParsers();
- generateUnknownFilter();
// not instantiable
try (MethodCreator mc = cc.getMethodCreator(MethodDescriptor.ofConstructor(CONFIG_CLASS_NAME))) {
mc.setModifiers(Opcodes.ACC_PRIVATE);
@@ -280,10 +281,13 @@ public static final class GenerateOperation implements AutoCloseable {
clinit = cc.getMethodCreator(MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "", void.class));
clinit.setModifiers(Opcodes.ACC_STATIC);
- cc.getFieldCreator(C_UNKNOWN).setModifiers(Opcodes.ACC_STATIC | Opcodes.ACC_FINAL);
+ cc.getFieldCreator(C_MAPPED_PROPERTIES).setModifiers(Opcodes.ACC_STATIC);
+ clinit.writeStaticField(C_MAPPED_PROPERTIES, clinit.invokeStaticMethod(C_GENERATE_MAPPED_PROPERTIES));
+
+ cc.getFieldCreator(C_UNKNOWN).setModifiers(Opcodes.ACC_STATIC);
clinit.writeStaticField(C_UNKNOWN, clinit.newInstance(HS_NEW));
- cc.getFieldCreator(C_UNKNOWN_RUNTIME).setModifiers(Opcodes.ACC_STATIC | Opcodes.ACC_FINAL);
+ cc.getFieldCreator(C_UNKNOWN_RUNTIME).setModifiers(Opcodes.ACC_STATIC);
clinit.writeStaticField(C_UNKNOWN_RUNTIME, clinit.newInstance(HS_NEW));
clinitNameBuilder = clinit.newInstance(SB_NEW);
@@ -457,10 +461,6 @@ public void run() {
// generate sweep for clinit
configSweepLoop(siParserBody, clinit, clinitConfig, getRegisteredRoots(BUILD_AND_RUN_TIME_FIXED), Type.BUILD_TIME);
-
- clinit.invokeStaticMethod(PU_FILTER_UNKNOWN,
- clinit.readStaticField(C_UNKNOWN),
- clinit.invokeStaticMethod(C_MAPPED_PROPERTIES));
clinit.invokeStaticMethod(CD_UNKNOWN_PROPERTIES, clinit.readStaticField(C_UNKNOWN));
if (liveReloadPossible) {
@@ -468,10 +468,6 @@ public void run() {
}
// generate sweep for run time
configSweepLoop(rtParserBody, readConfig, runTimeConfig, getRegisteredRoots(RUN_TIME), Type.RUNTIME);
-
- readConfig.invokeStaticMethod(PU_FILTER_UNKNOWN,
- readConfig.readStaticField(C_UNKNOWN_RUNTIME),
- readConfig.invokeStaticMethod(C_MAPPED_PROPERTIES));
readConfig.invokeStaticMethod(CD_UNKNOWN_PROPERTIES_RT, readConfig.readStaticField(C_UNKNOWN_RUNTIME));
// generate ensure-initialized method
@@ -525,33 +521,42 @@ public void run() {
private void configSweepLoop(MethodDescriptor parserBody, MethodCreator method, ResultHandle config,
Set registeredRoots, Type type) {
- ResultHandle nameSet;
- ResultHandle iterator;
+ ResultHandle propertyNames = method.invokeVirtualMethod(SRC_GET_PROPERTY_NAMES, config);
+ ResultHandle iterator = method.invokeInterfaceMethod(ITRA_ITERATOR, propertyNames);
- nameSet = filterProperties(method, config, registeredRoots);
- iterator = method.invokeInterfaceMethod(ITRA_ITERATOR, nameSet);
+ ResultHandle rootSet = method.newInstance(HS_NEW);
+ for (String registeredRoot : registeredRoots) {
+ method.invokeVirtualMethod(HS_ADD, rootSet, method.load(registeredRoot));
+ }
try (BytecodeCreator sweepLoop = method.createScope()) {
try (BytecodeCreator hasNext = sweepLoop.ifNonZero(sweepLoop.invokeInterfaceMethod(ITR_HAS_NEXT, iterator))
.trueBranch()) {
-
ResultHandle key = hasNext.checkCast(hasNext.invokeInterfaceMethod(ITR_NEXT, iterator), String.class);
+
+ // !mappedProperties.contains(new PropertyName(key)) continue sweepLoop;
+ hasNext.ifNonZero(
+ hasNext.invokeVirtualMethod(HS_CONTAINS, hasNext.readStaticField(C_MAPPED_PROPERTIES),
+ hasNext.newInstance(PN_NEW, key)))
+ .trueBranch().continueScope(sweepLoop);
+
// NameIterator keyIter = new NameIterator(key);
ResultHandle keyIter = hasNext.newInstance(NI_NEW_STRING, key);
- BranchResult unknownProperty = hasNext
+
+ // if (PropertiesUtil.isPropertyQuarkusCompoundName(keyIter))
+ BranchResult quarkusCompoundName = hasNext
.ifNonZero(hasNext.invokeStaticMethod(PU_IS_PROPERTY_QUARKUS_COMPOUND_NAME, keyIter));
- try (BytecodeCreator trueBranch = unknownProperty.trueBranch()) {
- ResultHandle unknown;
- if (type == Type.BUILD_TIME) {
- unknown = trueBranch.readStaticField(C_UNKNOWN);
- } else {
- unknown = trueBranch.readStaticField(C_UNKNOWN_RUNTIME);
- }
+ try (BytecodeCreator trueBranch = quarkusCompoundName.trueBranch()) {
+ ResultHandle unknown = type == Type.BUILD_TIME ? trueBranch.readStaticField(C_UNKNOWN)
+ : trueBranch.readStaticField(C_UNKNOWN_RUNTIME);
trueBranch.invokeVirtualMethod(HS_ADD, unknown, key);
}
+
+ hasNext.ifNonZero(hasNext.invokeStaticMethod(PU_IS_PROPERTY_IN_ROOTS, key, rootSet)).falseBranch()
+ .continueScope(sweepLoop);
+
// if (! keyIter.hasNext()) continue sweepLoop;
hasNext.ifNonZero(hasNext.invokeVirtualMethod(NI_HAS_NEXT, keyIter)).falseBranch().continueScope(sweepLoop);
- // if (! keyIter.nextSegmentEquals("quarkus")) continue sweepLoop;
// parse(config, keyIter);
hasNext.invokeStaticMethod(parserBody, config, keyIter);
// continue sweepLoop;
@@ -560,21 +565,6 @@ private void configSweepLoop(MethodDescriptor parserBody, MethodCreator method,
}
}
- private ResultHandle filterProperties(MethodCreator method, ResultHandle config, Set registeredRoots) {
- // Roots
- ResultHandle rootSet;
- rootSet = method.newInstance(HS_NEW);
- for (String registeredRoot : registeredRoots) {
- method.invokeVirtualMethod(HS_ADD, rootSet, method.load(registeredRoot));
- }
-
- // PropertyNames
- ResultHandle properties = method.invokeVirtualMethod(SRC_GET_PROPERTY_NAMES, config);
-
- // Filtered Properties
- return method.invokeStaticMethod(PU_FILTER_PROPERTIES_IN_ROOTS, properties, rootSet);
- }
-
private Set getRegisteredRoots(ConfigPhase configPhase) {
Set registeredRoots = new HashSet<>();
for (RootDefinition root : roots) {
@@ -1190,13 +1180,7 @@ private FieldDescriptor getOrCreateConverterInstance(Field field, ConverterType
return fd;
}
- static final MethodDescriptor KM_NEW = MethodDescriptor.ofConstructor(KeyMap.class);
- static final MethodDescriptor KM_FIND_OR_ADD = MethodDescriptor.ofMethod(KeyMap.class, "findOrAdd", KeyMap.class,
- String.class);
- static final MethodDescriptor KM_PUT_ROOT_VALUE = MethodDescriptor.ofMethod(KeyMap.class, "putRootValue", Object.class,
- Object.class);
-
- private void generateUnknownFilter() {
+ private void generateMappedProperties() {
Set names = new HashSet<>();
for (ConfigClass buildTimeMapping : buildTimeConfigResult.getBuildTimeMappings()) {
names.addAll(ConfigMappings.getProperties(buildTimeMapping).keySet());
@@ -1207,17 +1191,15 @@ private void generateUnknownFilter() {
for (ConfigClass runtimeConfigMapping : buildTimeConfigResult.getRunTimeMappings()) {
names.addAll(ConfigMappings.getProperties(runtimeConfigMapping).keySet());
}
+ Set propertyNames = PropertiesUtil.toPropertyNames(names);
- // Add a method that generates a KeyMap that can check if a property is mapped by a @ConfigMapping
- MethodCreator mc = cc.getMethodCreator(C_MAPPED_PROPERTIES);
+ MethodCreator mc = cc.getMethodCreator(C_GENERATE_MAPPED_PROPERTIES);
mc.setModifiers(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC);
- ResultHandle keyMap = mc.newInstance(KM_NEW);
- for (String name : names) {
- mc.invokeVirtualMethod(KM_PUT_ROOT_VALUE, mc.invokeVirtualMethod(KM_FIND_OR_ADD, keyMap, mc.load(name)),
- mc.load(true));
+ ResultHandle set = mc.newInstance(HS_NEW);
+ for (PropertyName propertyName : propertyNames) {
+ mc.invokeVirtualMethod(HS_ADD, set, mc.newInstance(PN_NEW, mc.load(propertyName.getName())));
}
-
- mc.returnValue(keyMap);
+ mc.returnValue(set);
mc.close();
}
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java
index fb8daf5b727cf..45cd6424d478a 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java
@@ -11,10 +11,12 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
+import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -24,6 +26,7 @@
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.NativeImageFeatureBuildItem;
+import io.quarkus.deployment.builditem.NativeMonitoringBuildItem;
import io.quarkus.deployment.builditem.SuppressNonRuntimeConfigChangedWarningBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ExcludeConfigBuildItem;
import io.quarkus.deployment.builditem.nativeimage.JPMSExportBuildItem;
@@ -115,6 +118,7 @@ ArtifactResultBuildItem nativeSourcesResult(NativeConfig nativeConfig,
List nativeImageSecurityProviders,
List nativeImageFeatures,
NativeImageRunnerBuildItem nativeImageRunner,
+ List nativeMonitoringBuildItems,
CurateOutcomeBuildItem curateOutcomeBuildItem) {
Path outputDir;
@@ -147,6 +151,7 @@ ArtifactResultBuildItem nativeSourcesResult(NativeConfig nativeConfig,
.setGraalVMVersion(GraalVM.Version.CURRENT)
.setNativeImageFeatures(nativeImageFeatures)
.setContainerBuild(nativeImageRunner.isContainerBuild())
+ .setNativeMonitoringOptions(nativeMonitoringBuildItems)
.build();
List command = nativeImageArgs.getArgs();
@@ -196,6 +201,7 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, LocalesBuildTimeCon
Optional processInheritIODisabledBuildItem,
List nativeImageFeatures,
Optional nativeImageAgentConfigDirectoryBuildItem,
+ List nativeMonitoringItems,
NativeImageRunnerBuildItem nativeImageRunner) {
if (nativeConfig.debug().enabled()) {
copyJarSourcesToLib(outputTargetBuildItem, curateOutcomeBuildItem);
@@ -254,6 +260,7 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, LocalesBuildTimeCon
.setBrokenClasspath(incompleteClassPathAllowed.isAllow())
.setNativeImageSecurityProviders(nativeImageSecurityProviders)
.setJPMSExportBuildItems(jpmsExportBuildItems)
+ .setNativeMonitoringOptions(nativeMonitoringItems)
.setEnableModules(enableModules)
.setNativeMinimalJavaVersions(nativeMinimalJavaVersions)
.setUnsupportedOSes(unsupportedOses)
@@ -605,6 +612,7 @@ static class Builder {
private List nativeMinimalJavaVersions;
private List unsupportedOSes;
private List nativeImageFeatures;
+ private List nativeMonitoringItems;
private Path outputDir;
private String runnerJarName;
private String pie = "";
@@ -713,6 +721,11 @@ public Builder setNativeImageName(String nativeImageName) {
return this;
}
+ public Builder setNativeMonitoringOptions(List options) {
+ this.nativeMonitoringItems = options;
+ return this;
+ }
+
@SuppressWarnings("deprecation")
public NativeImageInvokerInfo build() {
List nativeImageArgs = new ArrayList<>();
@@ -932,17 +945,23 @@ public NativeImageInvokerInfo build() {
nativeImageArgs.add("-march=" + nativeConfig.march().get());
}
- List monitoringOptions = new ArrayList<>();
+ Set monitoringOptions = new LinkedHashSet<>();
if (!OS.WINDOWS.isCurrent() || containerBuild) {
// --enable-monitoring=heapdump is not supported on Windows
monitoringOptions.add(NativeConfig.MonitoringOption.HEAPDUMP);
}
+
+ if (nativeMonitoringItems != null && !nativeMonitoringItems.isEmpty()) {
+ monitoringOptions.addAll(nativeMonitoringItems.stream()
+ .map(NativeMonitoringBuildItem::getOption)
+ .collect(Collectors.toSet()));
+ }
+
if (nativeConfig.monitoring().isPresent()) {
monitoringOptions.addAll(nativeConfig.monitoring().get());
}
if (!monitoringOptions.isEmpty()) {
nativeImageArgs.add("--enable-monitoring=" + monitoringOptions.stream()
- .distinct()
.map(o -> o.name().toLowerCase(Locale.ROOT)).collect(Collectors.joining(",")));
}
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigDescriptionBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigDescriptionBuildStep.java
index 4068bf65b1f16..df0e1ee7947d3 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigDescriptionBuildStep.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigDescriptionBuildStep.java
@@ -13,9 +13,6 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.OptionalDouble;
-import java.util.OptionalInt;
-import java.util.OptionalLong;
import java.util.Properties;
import java.util.Set;
import java.util.function.Consumer;
@@ -87,7 +84,7 @@ public void accept(Container node) {
String defaultDefault;
final Class> valueClass = field.getType();
- EffectiveConfigTypeAndValues effectiveConfigTypeAndValues = getTypeName(field);
+ EffectiveConfigTypeAndValues effectiveConfigTypeAndValues = getTypeName(valueClass, field.getGenericType());
if (valueClass == boolean.class) {
defaultDefault = "false";
@@ -112,8 +109,8 @@ public void accept(Container node) {
ret.add(new ConfigDescriptionBuildItem(name,
defVal,
javadoc.getProperty(javadocKey),
- effectiveConfigTypeAndValues.getTypeName(),
- effectiveConfigTypeAndValues.getAllowedValues(),
+ effectiveConfigTypeAndValues.typeName(),
+ effectiveConfigTypeAndValues.allowedValues(),
configPhase));
}
});
@@ -147,136 +144,75 @@ private void processMappings(List mappings, List valueClass = field.getType();
- return getTypeName(field, valueClass);
- }
-
- private EffectiveConfigTypeAndValues getTypeName(Field field, Class> valueClass) {
- EffectiveConfigTypeAndValues typeAndValues = new EffectiveConfigTypeAndValues();
- String name = valueClass.getName();
+ private EffectiveConfigTypeAndValues getTypeName(Class> valueClass, Type genericType) {
+ final String name;
+ final List allowedValues = new ArrayList<>();
// Extract Optionals, Lists and Sets
if ((valueClass.equals(Optional.class) || valueClass.equals(List.class) || valueClass.equals(Set.class))) {
-
- if (field != null) {
- Type genericType = field.getGenericType();
- name = genericType.getTypeName();
+ String thisName = valueClass.getName();
+ if (genericType != null) {
+ thisName = genericType.getTypeName();
}
- if (name.contains("<") && name.contains(">")) {
- name = name.substring(name.lastIndexOf("<") + 1, name.indexOf(">"));
+ if (thisName.contains("<") && thisName.contains(">")) {
+ thisName = thisName.substring(thisName.lastIndexOf("<") + 1, thisName.indexOf(">"));
}
try {
- Class> c = Class.forName(name);
- return getTypeName(null, c);
+ Class> c = Class.forName(thisName);
+ return getTypeName(c, null);
} catch (ClassNotFoundException ex) {
// Then we use the name as is.
}
- }
-
- // Check other optionals
- if (valueClass.equals(OptionalInt.class)) {
- name = Integer.class.getName();
- } else if (valueClass.equals(OptionalDouble.class)) {
- name = Double.class.getName();
- } else if (valueClass.equals(OptionalLong.class)) {
- name = Long.class.getName();
- }
-
- // Check if this is an enum
- if (Enum.class.isAssignableFrom(valueClass)) {
+ name = thisName;
+ } else if (Enum.class.isAssignableFrom(valueClass)) {
+ // Check if this is an enum
name = Enum.class.getName();
Object[] values = valueClass.getEnumConstants();
for (Object v : values) {
- Enum casted = (Enum) valueClass.cast(v);
- typeAndValues.addAllowedValue(casted.name());
+ Enum> casted = (Enum>) valueClass.cast(v);
+ allowedValues.add(casted.name());
}
+ } else {
+ // Map all primitives
+ name = switch (valueClass.getName()) {
+ case "java.util.OptionalInt", "int" -> Integer.class.getName();
+ case "boolean" -> Boolean.class.getName();
+ case "float" -> Float.class.getName();
+ case "java.util.OptionalDouble", "double" -> Double.class.getName();
+ case "java.util.OptionalLong", "long" -> Long.class.getName();
+ case "byte" -> Byte.class.getName();
+ case "short" -> Short.class.getName();
+ case "char" -> Character.class.getName();
+ default -> valueClass.getName();
+ };
}
// Special case for Log level
if (valueClass.isAssignableFrom(Level.class)) {
- typeAndValues.addAllowedValue(Level.ALL.getName());
- typeAndValues.addAllowedValue(Level.CONFIG.getName());
- typeAndValues.addAllowedValue(Level.FINE.getName());
- typeAndValues.addAllowedValue(Level.FINER.getName());
- typeAndValues.addAllowedValue(Level.FINEST.getName());
- typeAndValues.addAllowedValue(Level.INFO.getName());
- typeAndValues.addAllowedValue(Level.OFF.getName());
- typeAndValues.addAllowedValue(Level.SEVERE.getName());
- typeAndValues.addAllowedValue(Level.WARNING.getName());
- }
-
- // Map all primitives
- if (name.equals("int")) {
- name = Integer.class.getName();
- } else if (name.equals("boolean")) {
- name = Boolean.class.getName();
- } else if (name.equals("float")) {
- name = Float.class.getName();
- } else if (name.equals("double")) {
- name = Double.class.getName();
- } else if (name.equals("long")) {
- name = Long.class.getName();
- } else if (name.equals("byte")) {
- name = Byte.class.getName();
- } else if (name.equals("short")) {
- name = Short.class.getName();
- } else if (name.equals("char")) {
- name = Character.class.getName();
- }
-
- typeAndValues.setTypeName(name);
- return typeAndValues;
+ allowedValues.add(Level.ALL.getName());
+ allowedValues.add(Level.CONFIG.getName());
+ allowedValues.add(Level.FINE.getName());
+ allowedValues.add(Level.FINER.getName());
+ allowedValues.add(Level.FINEST.getName());
+ allowedValues.add(Level.INFO.getName());
+ allowedValues.add(Level.OFF.getName());
+ allowedValues.add(Level.SEVERE.getName());
+ allowedValues.add(Level.WARNING.getName());
+ }
+
+ return new EffectiveConfigTypeAndValues(name, allowedValues);
}
- static class EffectiveConfigTypeAndValues {
- private String typeName;
- private List allowedValues;
-
- public EffectiveConfigTypeAndValues() {
-
- }
-
- public EffectiveConfigTypeAndValues(String typeName) {
- this.typeName = typeName;
- }
-
- public EffectiveConfigTypeAndValues(String typeName, List allowedValues) {
- this.typeName = typeName;
- this.allowedValues = allowedValues;
- }
-
- public String getTypeName() {
- return typeName;
- }
-
- public void setTypeName(String typeName) {
- this.typeName = typeName;
- }
-
- public List getAllowedValues() {
- return allowedValues;
- }
-
- public void setAllowedValues(List allowedValues) {
- this.allowedValues = allowedValues;
- }
-
- public void addAllowedValue(String v) {
- if (allowedValues == null) {
- allowedValues = new ArrayList<>();
- }
- allowedValues.add(v);
- }
+ private record EffectiveConfigTypeAndValues(String typeName, List allowedValues) {
}
}
diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java
index 0a7b27e0f52cf..18978d1714028 100644
--- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java
+++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java
@@ -1,86 +1,14 @@
package io.quarkus.runtime.configuration;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
-import io.smallrye.config.KeyMap;
+import io.smallrye.config.PropertyName;
public class PropertiesUtil {
private PropertiesUtil() {
- }
-
- /**
- * @deprecated Use {@link PropertiesUtil#filterPropertiesInRoots(Iterable, Set)} instead.
- */
- @Deprecated(forRemoval = true)
- public static boolean isPropertyInRoot(Set roots, NameIterator propertyName) {
- for (String root : roots) {
- // match everything
- if (root.length() == 0) {
- return true;
- }
-
- // A sub property from a namespace is always bigger
- if (propertyName.getName().length() <= root.length()) {
- continue;
- }
-
- final NameIterator rootNi = new NameIterator(root);
- // compare segments
- while (rootNi.hasNext()) {
- String segment = rootNi.getNextSegment();
- if (!propertyName.hasNext()) {
- propertyName.goToStart();
- break;
- }
-
- final String nextSegment = propertyName.getNextSegment();
- if (!segment.equals(nextSegment)) {
- propertyName.goToStart();
- break;
- }
-
- rootNi.next();
- propertyName.next();
-
- // root has no more segments, and we reached this far so everything matched.
- // on top, property still has more segments to do the mapping.
- if (!rootNi.hasNext() && propertyName.hasNext()) {
- propertyName.goToStart();
- return true;
- }
- }
- }
-
- return false;
- }
-
- public static Iterable filterPropertiesInRoots(final Iterable properties, final Set roots) {
- if (roots.isEmpty()) {
- return properties;
- }
-
- // Will match everything, so no point in filtering
- if (roots.contains("")) {
- return properties;
- }
-
- List matchedProperties = new ArrayList<>();
- for (String property : properties) {
- // This is a Quarkus compound name, usually by setting something like `quarkus.foo.bar` in the YAML source
- // TODO - We let it through to match it later again to place it in the right unknown reporting (static or runtime). We can improve this too.
- if (property.startsWith("\"quarkus.")) {
- matchedProperties.add(property);
- continue;
- }
-
- if (isPropertyInRoots(property, roots)) {
- matchedProperties.add(property);
- }
- }
- return matchedProperties;
+ throw new IllegalStateException("Utility class");
}
public static boolean isPropertyInRoots(final String property, final Set roots) {
@@ -121,23 +49,27 @@ public static boolean isPropertyQuarkusCompoundName(NameIterator propertyName) {
return propertyName.getName().startsWith("\"quarkus.");
}
- /**
- * Removes false positives of configuration properties marked as unknown. To populate the old @ConfigRoot, all
- * properties are iterated and matched against known roots. With @ConfigMapping the process is different, so
- * properties that are known to @ConfigMapping are not known to the @ConfigRoot, so they will be marked as being
- * unknown. It is a bit easier to just double-check on the unknown properties and remove these false positives by
- * matching them against the known properties of @ConfigMapping.
- *
- * @param unknownProperties the collected unknown properties from the old @ConfigRoot mapping
- * @param filterPatterns the mapped patterns from the discovered @ConfigMapping
- */
- public static void filterUnknown(Set unknownProperties, KeyMap filterPatterns) {
- Set toRemove = new HashSet<>();
- for (String unknownProperty : unknownProperties) {
- if (filterPatterns.hasRootValue(unknownProperty)) {
- toRemove.add(unknownProperty);
+ public static Set toPropertyNames(final Set names) {
+ Map propertyNames = new HashMap<>();
+ for (String name : names) {
+ PropertyName propertyName = new PropertyName(name);
+ if (propertyNames.containsKey(propertyName)) {
+ String existing = propertyNames.remove(propertyName);
+ if (existing.length() < name.length()) {
+ propertyNames.put(new PropertyName(existing), existing);
+ } else if (existing.length() > name.length()) {
+ propertyNames.put(propertyName, name);
+ } else {
+ if (existing.indexOf('*') <= name.indexOf('*')) {
+ propertyNames.put(new PropertyName(existing), existing);
+ } else {
+ propertyNames.put(propertyName, name);
+ }
+ }
+ } else {
+ propertyNames.put(propertyName, name);
}
}
- unknownProperties.removeAll(toRemove);
+ return propertyNames.keySet();
}
}
diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/QuarkusPlugin.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/QuarkusPlugin.java
index 15d58e6c94f71..0a849539e132b 100644
--- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/QuarkusPlugin.java
+++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/QuarkusPlugin.java
@@ -139,10 +139,6 @@ public void apply(Project project) {
// Apply the `java` plugin
project.getPluginManager().apply(JavaPlugin.class);
- project.getGradle().getSharedServices().registerIfAbsent("forcedPropertiesService", ForcedPropertieBuildService.class,
- spec -> {
- });
-
registerModel();
// register extension
@@ -156,7 +152,11 @@ public void apply(Project project) {
private void registerTasks(Project project, QuarkusPluginExtension quarkusExt) {
TaskContainer tasks = project.getTasks();
-
+ String forcedPropertiesService = String.format("forcedPropertiesService-%s", project.getName());
+ Provider serviceProvider = project.getGradle().getSharedServices().registerIfAbsent(
+ forcedPropertiesService, ForcedPropertieBuildService.class,
+ spec -> {
+ });
final String devRuntimeConfigName = ApplicationDeploymentClasspathBuilder
.getBaseRuntimeConfigName(LaunchMode.DEVELOPMENT);
final Configuration devRuntimeDependencies = project.getConfigurations().maybeCreate(devRuntimeConfigName);
@@ -236,19 +236,16 @@ private void registerTasks(Project project, QuarkusPluginExtension quarkusExt) {
});
tasks.register(QUARKUS_SHOW_EFFECTIVE_CONFIG_TASK_NAME,
QuarkusShowEffectiveConfig.class, task -> {
- configureQuarkusBuildTask(project, quarkusExt, task, quarkusBuildAppModelTask);
+ configureQuarkusBuildTask(project, task, quarkusBuildAppModelTask, serviceProvider);
task.setDescription("Show effective Quarkus build configuration.");
});
TaskProvider quarkusBuildDependencies = tasks.register(QUARKUS_BUILD_DEP_TASK_NAME,
QuarkusBuildDependencies.class,
task -> {
- configureQuarkusBuildTask(project, quarkusExt, task, quarkusBuildAppModelTask);
+ configureQuarkusBuildTask(project, task, quarkusBuildAppModelTask, serviceProvider);
task.getOutputs().doNotCacheIf("Dependencies are never cached", t -> true);
- task.getApplicationModel()
- .set(quarkusGenerateAppModelTask.flatMap(QuarkusApplicationModelTask::getApplicationModel));
-
});
Property cacheLargeArtifacts = quarkusExt.getCacheLargeArtifacts();
@@ -256,7 +253,7 @@ private void registerTasks(Project project, QuarkusPluginExtension quarkusExt) {
TaskProvider quarkusBuildCacheableAppParts = tasks.register(
QUARKUS_BUILD_APP_PARTS_TASK_NAME,
QuarkusBuildCacheableAppParts.class, task -> {
- configureQuarkusBuildTask(project, quarkusExt, task, quarkusBuildAppModelTask);
+ configureQuarkusBuildTask(project, task, quarkusBuildAppModelTask, serviceProvider);
task.dependsOn(quarkusGenerateCode);
task.getOutputs().doNotCacheIf(
"Not adding uber-jars, native binaries and mutable-jar package type to Gradle " +
@@ -272,7 +269,7 @@ public boolean isSatisfiedBy(Task t) {
});
TaskProvider quarkusBuild = tasks.register(QUARKUS_BUILD_TASK_NAME, QuarkusBuild.class, build -> {
- configureQuarkusBuildTask(project, quarkusExt, build, quarkusBuildAppModelTask);
+ configureQuarkusBuildTask(project, build, quarkusBuildAppModelTask, serviceProvider);
build.dependsOn(quarkusBuildDependencies, quarkusBuildCacheableAppParts);
build.getOutputs().doNotCacheIf(
"Only collects and combines the outputs of " + QUARKUS_BUILD_APP_PARTS_TASK_NAME + " and "
@@ -296,29 +293,20 @@ public boolean isSatisfiedBy(Task t) {
tasks.register(IMAGE_BUILD_TASK_NAME, ImageBuild.class, task -> {
task.dependsOn(quarkusRequiredExtension);
- configureQuarkusBuildTask(project, quarkusExt, task, quarkusBuildAppModelTask);
+ configureQuarkusBuildTask(project, task, quarkusBuildAppModelTask, serviceProvider);
task.getBuilderName().set(quarkusRequiredExtension.flatMap(ImageCheckRequirementsTask::getOutputFile));
- task.getOutputs().doNotCacheIf("Dependencies are never cached", t -> true);
- task.getApplicationModel()
- .set(quarkusGenerateAppModelTask.flatMap(QuarkusApplicationModelTask::getApplicationModel));
task.finalizedBy(quarkusBuild);
});
tasks.register(IMAGE_PUSH_TASK_NAME, ImagePush.class, task -> {
task.dependsOn(quarkusRequiredExtension);
- configureQuarkusBuildTask(project, quarkusExt, task, quarkusBuildAppModelTask);
+ configureQuarkusBuildTask(project, task, quarkusBuildAppModelTask, serviceProvider);
task.getBuilderName().set(quarkusRequiredExtension.flatMap(ImageCheckRequirementsTask::getOutputFile));
- task.getOutputs().doNotCacheIf("Dependencies are never cached", t -> true);
- task.getApplicationModel()
- .set(quarkusGenerateAppModelTask.flatMap(QuarkusApplicationModelTask::getApplicationModel));
task.finalizedBy(quarkusBuild);
});
tasks.register(DEPLOY_TASK_NAME, Deploy.class, task -> {
- configureQuarkusBuildTask(project, quarkusExt, task, quarkusBuildAppModelTask);
- task.getOutputs().doNotCacheIf("Dependencies are never cached", t -> true);
- task.getApplicationModel()
- .set(quarkusGenerateAppModelTask.flatMap(QuarkusApplicationModelTask::getApplicationModel));
+ configureQuarkusBuildTask(project, task, quarkusBuildAppModelTask, serviceProvider);
task.finalizedBy(quarkusBuild);
});
@@ -326,10 +314,7 @@ public boolean isSatisfiedBy(Task t) {
quarkusExt);
TaskProvider quarkusRun = tasks.register(QUARKUS_RUN_TASK_NAME, QuarkusRun.class,
build -> {
- configureQuarkusBuildTask(project, quarkusExt, build, quarkusBuildAppModelTask);
- build.getOutputs().doNotCacheIf("Dependencies are never cached", t -> true);
- build.getApplicationModel()
- .set(quarkusGenerateAppModelTask.flatMap(QuarkusApplicationModelTask::getApplicationModel));
+ configureQuarkusBuildTask(project, build, quarkusBuildAppModelTask, serviceProvider);
build.dependsOn(quarkusBuild);
});
@@ -527,10 +512,13 @@ private static void configureApplicationModelTask(Project project, QuarkusApplic
task.getApplicationModel().set(project.getLayout().getBuildDirectory().file(quarkusModelFile));
}
- private static void configureQuarkusBuildTask(Project project, QuarkusPluginExtension quarkusExt, QuarkusBuildTask task,
- TaskProvider quarkusGenerateAppModelTask) {
+ private static void configureQuarkusBuildTask(Project project, QuarkusBuildTask task,
+ TaskProvider quarkusGenerateAppModelTask,
+ Provider serviceProvider) {
task.getApplicationModel().set(quarkusGenerateAppModelTask.flatMap(QuarkusApplicationModelTask::getApplicationModel));
SourceSet mainSourceSet = getSourceSet(project, SourceSet.MAIN_SOURCE_SET_NAME);
+ task.getAdditionalForcedProperties().set(serviceProvider);
+ task.usesService(serviceProvider);
task.setCompileClasspath(mainSourceSet.getCompileClasspath().plus(mainSourceSet.getRuntimeClasspath())
.plus(mainSourceSet.getAnnotationProcessorPath())
.plus(mainSourceSet.getResources()));
diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusBuildTask.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusBuildTask.java
index f54010f9aba90..f5f75c86681ed 100644
--- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusBuildTask.java
+++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusBuildTask.java
@@ -17,10 +17,10 @@
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.logging.LogLevel;
import org.gradle.api.provider.Property;
-import org.gradle.api.services.ServiceReference;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
+import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity;
@@ -48,8 +48,8 @@ public abstract class QuarkusBuildTask extends QuarkusTask {
static final String NATIVE_SOURCES = "native-sources";
private final QuarkusPluginExtensionView extensionView;
- @ServiceReference("forcedPropertiesService")
- abstract Property getAdditionalForcedProperties();
+ @Internal
+ public abstract Property getAdditionalForcedProperties();
QuarkusBuildTask(String description, boolean compatible) {
super(description, compatible);
@@ -272,7 +272,7 @@ void generateBuild() {
.collect(Collectors.joining("\n ", "\n ", "")));
}
- WorkQueue workQueue = workQueue(quarkusProperties, getExtensionView().getCodeGenForkOptions().get());
+ WorkQueue workQueue = workQueue(quarkusProperties, getExtensionView().getBuildForkOptions().get());
workQueue.submit(BuildWorker.class, params -> {
params.getBuildSystemProperties()
diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java
index 5cc8b1319ac2f..50018c18c965e 100644
--- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java
+++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java
@@ -551,18 +551,41 @@ protected void modifyDevModeContext(GradleDevModeLauncher.Builder builder) {
private void addQuarkusDevModeDeps(GradleDevModeLauncher.Builder builder, ApplicationModel appModel) {
- ResolvedDependency coreDeployment = null;
- for (ResolvedDependency d : appModel.getDependencies()) {
- if (d.isDeploymentCp() && d.getArtifactId().equals("quarkus-core-deployment")
- && d.getGroupId().equals("io.quarkus")) {
- coreDeployment = d;
- break;
- }
+ var devModeDependencyConfiguration = getProject().getConfigurations()
+ .findByName(ApplicationDeploymentClasspathBuilder.QUARKUS_BOOTSTRAP_RESOLVER_CONFIGURATION);
+ if (devModeDependencyConfiguration == null) {
+ final Configuration platformConfig = getProject().getConfigurations().findByName(
+ ToolingUtils.toPlatformConfigurationName(
+ ApplicationDeploymentClasspathBuilder.getFinalRuntimeConfigName(LaunchMode.DEVELOPMENT)));
+ getProject().getConfigurations().register(
+ ApplicationDeploymentClasspathBuilder.QUARKUS_BOOTSTRAP_RESOLVER_CONFIGURATION,
+ configuration -> {
+ configuration.setCanBeConsumed(false);
+ configuration.extendsFrom(platformConfig);
+ configuration.getDependencies().add(getQuarkusGradleBootstrapResolver());
+ configuration.getDependencies().add(getQuarkusCoreDeployment(appModel));
+ });
+ devModeDependencyConfiguration = getProject().getConfigurations()
+ .getByName(ApplicationDeploymentClasspathBuilder.QUARKUS_BOOTSTRAP_RESOLVER_CONFIGURATION);
}
- if (coreDeployment == null) {
- throw new GradleException("Failed to locate io.quarkus:quarkus-core-deployment on the application build classpath");
+
+ for (ResolvedArtifact appDep : devModeDependencyConfiguration.getResolvedConfiguration().getResolvedArtifacts()) {
+ ModuleVersionIdentifier artifactId = appDep.getModuleVersion().getId();
+ //we only use the launcher for launching from the IDE, we need to exclude it
+ if (!(artifactId.getGroup().equals("io.quarkus")
+ && artifactId.getName().equals("quarkus-ide-launcher"))) {
+ if (artifactId.getGroup().equals("io.quarkus")
+ && artifactId.getName().equals("quarkus-class-change-agent")) {
+ builder.jvmArgs("-javaagent:" + appDep.getFile().getAbsolutePath());
+ } else {
+ builder.classpathEntry(ArtifactKey.of(appDep.getModuleVersion().getId().getGroup(), appDep.getName(),
+ appDep.getClassifier(), appDep.getExtension()), appDep.getFile());
+ }
+ }
}
+ }
+ private Dependency getQuarkusGradleBootstrapResolver() {
final String pomPropsPath = "META-INF/maven/io.quarkus/quarkus-bootstrap-gradle-resolver/pom.properties";
final InputStream devModePomPropsIs = DevModeMain.class.getClassLoader().getResourceAsStream(pomPropsPath);
if (devModePomPropsIs == null) {
@@ -586,38 +609,26 @@ private void addQuarkusDevModeDeps(GradleDevModeLauncher.Builder builder, Applic
if (devModeVersion == null) {
throw new GradleException("Classpath resource " + pomPropsPath + " is missing version");
}
-
Dependency gradleResolverDep = getProject().getDependencies()
.create(String.format("%s:%s:%s", devModeGroupId, devModeArtifactId, devModeVersion));
- Dependency coreDeploymentDep = getProject().getDependencies()
- .create(String.format("%s:%s:%s", coreDeployment.getGroupId(), coreDeployment.getArtifactId(),
- coreDeployment.getVersion()));
-
- final Configuration devModeDependencyConfiguration = getProject().getConfigurations()
- .detachedConfiguration(gradleResolverDep, coreDeploymentDep);
-
- final String platformConfigName = ToolingUtils.toPlatformConfigurationName(
- ApplicationDeploymentClasspathBuilder.getFinalRuntimeConfigName(LaunchMode.DEVELOPMENT));
- final Configuration platformConfig = getProject().getConfigurations().findByName(platformConfigName);
- if (platformConfig != null) {
- // apply the platforms
- devModeDependencyConfiguration.extendsFrom(platformConfig);
- }
+ return gradleResolverDep;
+ }
- for (ResolvedArtifact appDep : devModeDependencyConfiguration.getResolvedConfiguration().getResolvedArtifacts()) {
- ModuleVersionIdentifier artifactId = appDep.getModuleVersion().getId();
- //we only use the launcher for launching from the IDE, we need to exclude it
- if (!(artifactId.getGroup().equals("io.quarkus")
- && artifactId.getName().equals("quarkus-ide-launcher"))) {
- if (artifactId.getGroup().equals("io.quarkus")
- && artifactId.getName().equals("quarkus-class-change-agent")) {
- builder.jvmArgs("-javaagent:" + appDep.getFile().getAbsolutePath());
- } else {
- builder.classpathEntry(ArtifactKey.of(appDep.getModuleVersion().getId().getGroup(), appDep.getName(),
- appDep.getClassifier(), appDep.getExtension()), appDep.getFile());
- }
+ private Dependency getQuarkusCoreDeployment(ApplicationModel appModel) {
+ ResolvedDependency coreDeployment = null;
+ for (ResolvedDependency d : appModel.getDependencies()) {
+ if (d.isDeploymentCp() && d.getArtifactId().equals("quarkus-core-deployment")
+ && d.getGroupId().equals("io.quarkus")) {
+ coreDeployment = d;
+ break;
}
}
+ if (coreDeployment == null) {
+ throw new GradleException("Failed to locate io.quarkus:quarkus-core-deployment on the application build classpath");
+ }
+ return getProject().getDependencies()
+ .create(String.format("%s:%s:%s", coreDeployment.getGroupId(), coreDeployment.getArtifactId(),
+ coreDeployment.getVersion()));
}
private void addLocalProject(ResolvedDependency project, GradleDevModeLauncher.Builder builder, Set addeDeps,
diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusPluginExtensionView.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusPluginExtensionView.java
index f4a8e87aba3d9..9dc97a6c53ea7 100644
--- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusPluginExtensionView.java
+++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusPluginExtensionView.java
@@ -64,6 +64,7 @@ public QuarkusPluginExtensionView(Project project, QuarkusPluginExtension extens
getCleanupBuildOutput().set(extension.getCleanupBuildOutput());
getFinalName().set(extension.getFinalName());
getCodeGenForkOptions().set(getProviderFactory().provider(() -> extension.codeGenForkOptions));
+ getBuildForkOptions().set(getProviderFactory().provider(() -> extension.buildForkOptions));
getIgnoredEntries().set(extension.ignoredEntriesProperty());
getMainResources().setFrom(project.getExtensions().getByType(SourceSetContainer.class).getByName(MAIN_SOURCE_SET_NAME)
.getResources().getSourceDirectories());
@@ -127,6 +128,9 @@ private Provider