diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/ClassLoadingConfig.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/ClassLoadingConfig.java index 3eb7b693f46ec..ae14536df79d6 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/ClassLoadingConfig.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/ClassLoadingConfig.java @@ -6,9 +6,9 @@ import java.util.Set; import io.quarkus.runtime.annotations.ConfigDocMapKey; -import io.quarkus.runtime.annotations.ConfigItem; import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; +import io.smallrye.config.ConfigMapping; /** * Class loading @@ -18,7 +18,8 @@ * This is because it is needed before any of the config infrastructure is set up. */ @ConfigRoot(phase = ConfigPhase.BUILD_TIME) -public class ClassLoadingConfig { +@ConfigMapping(prefix = "quarkus.class-loading") +public interface ClassLoadingConfig { /** * Artifacts that are loaded in a parent first manner. This can be used to work around issues where a given @@ -30,8 +31,7 @@ public class ClassLoadingConfig { *

* WARNING: This config property can only be set in application.properties */ - @ConfigItem(defaultValue = "") - public Optional> parentFirstArtifacts; + Optional> parentFirstArtifacts(); /** * Artifacts that are loaded in the runtime ClassLoader in dev mode, so they will be dropped @@ -48,15 +48,13 @@ public class ClassLoadingConfig { *

* WARNING: This config property can only be set in application.properties */ - @ConfigItem(defaultValue = "") - public Optional reloadableArtifacts; + Optional reloadableArtifacts(); /** * Artifacts that will never be loaded by the class loader, and will not be packed into the final application. This allows * you to explicitly remove artifacts from your application even though they may be present on the class path. */ - @ConfigItem(defaultValue = "") - public Optional> removedArtifacts; + Optional> removedArtifacts(); /** * Resources that should be removed/hidden from dependencies. @@ -73,8 +71,7 @@ public class ClassLoadingConfig { *

* Note that for technical reasons this is not supported when running with JBang. */ - @ConfigItem @ConfigDocMapKey("group-id:artifact-id") - public Map> removedResources; + Map> removedResources(); } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/index/ApplicationArchiveBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/index/ApplicationArchiveBuildStep.java index 4efa94db2d4ca..0eb9f56003939 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/index/ApplicationArchiveBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/index/ApplicationArchiveBuildStep.java @@ -117,7 +117,7 @@ ApplicationArchivesBuildItem build( } Map> removedResources = new HashMap<>(); - for (Map.Entry> entry : classLoadingConfig.removedResources.entrySet()) { + for (Map.Entry> entry : classLoadingConfig.removedResources().entrySet()) { removedResources.put(new GACT(entry.getKey().split(":")), entry.getValue()); } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java index bd36f8ba78ae9..b9d5b25fb68ae 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java @@ -1,7 +1,6 @@ package io.quarkus.deployment.pkg.steps; import static io.quarkus.commons.classloading.ClassLoaderHelper.fromClassNameToResourceName; -import static io.quarkus.deployment.pkg.PackageConfig.JarConfig.JarType.LEGACY_JAR; import static io.quarkus.deployment.pkg.PackageConfig.JarConfig.JarType.MUTABLE_JAR; import static io.quarkus.deployment.pkg.PackageConfig.JarConfig.JarType.UBER_JAR; @@ -358,7 +357,7 @@ private void buildUberJar0(CurateOutcomeBuildItem curateOutcomeBuildItem, final Set mergeResourcePaths = mergedResources.stream() .map(UberJarMergedResourceBuildItem::getPath) .collect(Collectors.toSet()); - final Set removed = getRemovedKeys(classLoadingConfig); + final Set removed = getRemovedArtifactKeys(classLoadingConfig); Set ignoredEntries = new HashSet<>(); packageConfig.jar().userConfiguredIgnoredEntries().ifPresent(ignoredEntries::addAll); @@ -554,7 +553,7 @@ private JarBuildItem buildLegacyThinJar(CurateOutcomeBuildItem curateOutcomeBuil doLegacyThinJarGeneration(curateOutcomeBuildItem, outputTargetBuildItem, transformedClasses, applicationArchivesBuildItem, applicationInfo, packageConfig, generatedResources, libDir, generatedClasses, runnerZipFs, mainClassBuildItem, - classLoadingConfig); + getRemovedArtifactKeys(classLoadingConfig)); } runnerJar.toFile().setReadable(true, false); @@ -707,7 +706,7 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem, } final Set parentFirstKeys = getParentFirstKeys(curateOutcomeBuildItem, classLoadingConfig); final StringBuilder classPath = new StringBuilder(); - final Set removed = getRemovedKeys(classLoadingConfig); + final Set removed = getRemovedArtifactKeys(classLoadingConfig); final Map> copiedArtifacts = new HashMap<>(); for (ResolvedDependency appDep : curateOutcomeBuildItem.getApplicationModel().getRuntimeDependencies()) { if (!rebuild) { @@ -882,7 +881,7 @@ private Set getParentFirstKeys(CurateOutcomeBuildItem curateOutcome parentFirstKeys.add(d.getKey()); } }); - classLoadingConfig.parentFirstArtifacts.ifPresent( + classLoadingConfig.parentFirstArtifacts().ifPresent( parentFirstArtifacts -> { for (String artifact : parentFirstArtifacts) { parentFirstKeys.add(new GACT(artifact.split(":"))); @@ -891,18 +890,16 @@ private Set getParentFirstKeys(CurateOutcomeBuildItem curateOutcome return parentFirstKeys; } - /** - * @return a {@code Set} containing the key of the artifacts to load from the parent ClassLoader first. - */ - private Set getRemovedKeys(ClassLoadingConfig classLoadingConfig) { - final Set removed = new HashSet<>(); - classLoadingConfig.removedArtifacts.ifPresent( - removedArtifacts -> { - for (String artifact : removedArtifacts) { - removed.add(new GACT(artifact.split(":"))); - } - }); - return removed; + private Set getRemovedArtifactKeys(ClassLoadingConfig classLoadingConfig) { + if (classLoadingConfig.removedArtifacts().isEmpty()) { + return Set.of(); + } + + Set removedArtifacts = new HashSet<>(); + for (String artifact : classLoadingConfig.removedArtifacts().get()) { + removedArtifacts.add(GACT.fromString(artifact)); + } + return Collections.unmodifiableSet(removedArtifacts); } private void copyDependency(Set parentFirstArtifacts, OutputTargetBuildItem outputTargetBuildItem, @@ -1044,16 +1041,13 @@ private NativeImageSourceJarBuildItem buildNativeImageThinJar(CurateOutcomeBuild log.info("Building native image source jar: " + runnerJar); + final Set removedArtifacts = new HashSet<>(getRemovedArtifactKeys(classLoadingConfig)); // Remove svm and graal-sdk artifacts as they are provided by GraalVM itself - if (classLoadingConfig.removedArtifacts.isEmpty()) { - classLoadingConfig.removedArtifacts = Optional.of(new ArrayList<>(6)); - } - List removedArtifacts = classLoadingConfig.removedArtifacts.get(); - removedArtifacts.add("org.graalvm.nativeimage:svm"); - removedArtifacts.add("org.graalvm.sdk:graal-sdk"); - removedArtifacts.add("org.graalvm.sdk:nativeimage"); - removedArtifacts.add("org.graalvm.sdk:word"); - removedArtifacts.add("org.graalvm.sdk:collections"); + removedArtifacts.add(GACT.fromString("org.graalvm.nativeimage:svm")); + removedArtifacts.add(GACT.fromString("org.graalvm.sdk:graal-sdk")); + removedArtifacts.add(GACT.fromString("org.graalvm.sdk:nativeimage")); + removedArtifacts.add(GACT.fromString("org.graalvm.sdk:word")); + removedArtifacts.add(GACT.fromString("org.graalvm.sdk:collections")); // complain if graal-sdk is present as a dependency as nativeimage should be preferred if (curateOutcomeBuildItem.getApplicationModel().getDependencies().stream() @@ -1065,7 +1059,7 @@ private NativeImageSourceJarBuildItem buildNativeImageThinJar(CurateOutcomeBuild doLegacyThinJarGeneration(curateOutcomeBuildItem, outputTargetBuildItem, transformedClasses, applicationArchivesBuildItem, applicationInfo, packageConfig, generatedResources, libDir, allClasses, - runnerZipFs, mainClassBuildItem, classLoadingConfig); + runnerZipFs, mainClassBuildItem, removedArtifacts); } runnerJar.toFile().setReadable(true, false); return new NativeImageSourceJarBuildItem(runnerJar, libDir); @@ -1109,7 +1103,7 @@ private void doLegacyThinJarGeneration(CurateOutcomeBuildItem curateOutcomeBuild List allClasses, FileSystem runnerZipFs, MainClassBuildItem mainClassBuildItem, - ClassLoadingConfig classLoadingConfig) + Set removedArtifacts) throws IOException { final Map seen = new HashMap<>(); final StringBuilder classPath = new StringBuilder(); @@ -1120,9 +1114,8 @@ private void doLegacyThinJarGeneration(CurateOutcomeBuildItem curateOutcomeBuild Predicate ignoredEntriesPredicate = getThinJarIgnoredEntriesPredicate(packageConfig); - final Set removed = getRemovedKeys(classLoadingConfig); copyLibraryJars(runnerZipFs, outputTargetBuildItem, transformedClasses, libDir, classPath, appDeps, services, - ignoredEntriesPredicate, removed); + ignoredEntriesPredicate, removedArtifacts); ResolvedDependency appArtifact = curateOutcomeBuildItem.getApplicationModel().getAppArtifact(); // the manifest needs to be the first entry in the jar, otherwise JarInputStream does not work properly diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/ApplicationIndexBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/ApplicationIndexBuildStep.java index b90e9592f69e4..bff7b73344d81 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/steps/ApplicationIndexBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/ApplicationIndexBuildStep.java @@ -84,7 +84,7 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx private Set removedApplicationClasses(CurateOutcomeBuildItem curation, ClassLoadingConfig classLoadingConfig) { ResolvedDependency appArtifact = curation.getApplicationModel().getAppArtifact(); - Set entry = classLoadingConfig.removedResources + Set entry = classLoadingConfig.removedResources() .get(appArtifact.getGroupId() + ":" + appArtifact.getArtifactId()); return entry != null ? entry : Collections.emptySet(); } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/ClassTransformingBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/ClassTransformingBuildStep.java index 921cb5fc8993e..fe0ed1f052263 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/steps/ClassTransformingBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/ClassTransformingBuildStep.java @@ -88,7 +88,7 @@ TransformedClassesBuildItem handleClassTransformation(List removedResourceBuildItems) { //a little bit of a hack, but we use an empty transformed class to represent removed resources, as transforming a class removes it from the original archive Map> removed = new HashMap<>(); - for (Map.Entry> entry : classLoadingConfig.removedResources.entrySet()) { + for (Map.Entry> entry : classLoadingConfig.removedResources().entrySet()) { removed.put(new GACT(entry.getKey().split(":")), entry.getValue()); } for (RemovedResourceBuildItem i : removedResourceBuildItems) {