Skip to content

Commit

Permalink
Core - ClassLoadingConfig - Switch to @ConfigMapping
Browse files Browse the repository at this point in the history
Part of quarkusio#45446

This is the last remaining piece in core except for the compatibility
layer for Dev Services config, that we will drop at some point.
  • Loading branch information
gsmet committed Feb 5, 2025
1 parent 49c8fe9 commit 8a6fc13
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -30,8 +31,7 @@ public class ClassLoadingConfig {
* <p>
* WARNING: This config property can only be set in application.properties
*/
@ConfigItem(defaultValue = "")
public Optional<List<String>> parentFirstArtifacts;
Optional<List<String>> parentFirstArtifacts();

/**
* Artifacts that are loaded in the runtime ClassLoader in dev mode, so they will be dropped
Expand All @@ -48,15 +48,13 @@ public class ClassLoadingConfig {
* <p>
* WARNING: This config property can only be set in application.properties
*/
@ConfigItem(defaultValue = "")
public Optional<String> reloadableArtifacts;
Optional<String> 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<List<String>> removedArtifacts;
Optional<List<String>> removedArtifacts();

/**
* Resources that should be removed/hidden from dependencies.
Expand All @@ -73,8 +71,7 @@ public class ClassLoadingConfig {
* <p>
* Note that for technical reasons this is not supported when running with JBang.
*/
@ConfigItem
@ConfigDocMapKey("group-id:artifact-id")
public Map<String, Set<String>> removedResources;
Map<String, Set<String>> removedResources();

}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ ApplicationArchivesBuildItem build(
}

Map<ArtifactKey, Set<String>> removedResources = new HashMap<>();
for (Map.Entry<String, Set<String>> entry : classLoadingConfig.removedResources.entrySet()) {
for (Map.Entry<String, Set<String>> entry : classLoadingConfig.removedResources().entrySet()) {
removedResources.put(new GACT(entry.getKey().split(":")), entry.getValue());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -358,7 +357,7 @@ private void buildUberJar0(CurateOutcomeBuildItem curateOutcomeBuildItem,
final Set<String> mergeResourcePaths = mergedResources.stream()
.map(UberJarMergedResourceBuildItem::getPath)
.collect(Collectors.toSet());
final Set<ArtifactKey> removed = getRemovedKeys(classLoadingConfig);
final Set<ArtifactKey> removed = getRemovedArtifactKeys(classLoadingConfig);

Set<String> ignoredEntries = new HashSet<>();
packageConfig.jar().userConfiguredIgnoredEntries().ifPresent(ignoredEntries::addAll);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -707,7 +706,7 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem,
}
final Set<ArtifactKey> parentFirstKeys = getParentFirstKeys(curateOutcomeBuildItem, classLoadingConfig);
final StringBuilder classPath = new StringBuilder();
final Set<ArtifactKey> removed = getRemovedKeys(classLoadingConfig);
final Set<ArtifactKey> removed = getRemovedArtifactKeys(classLoadingConfig);
final Map<ArtifactKey, List<Path>> copiedArtifacts = new HashMap<>();
for (ResolvedDependency appDep : curateOutcomeBuildItem.getApplicationModel().getRuntimeDependencies()) {
if (!rebuild) {
Expand Down Expand Up @@ -882,7 +881,7 @@ private Set<ArtifactKey> getParentFirstKeys(CurateOutcomeBuildItem curateOutcome
parentFirstKeys.add(d.getKey());
}
});
classLoadingConfig.parentFirstArtifacts.ifPresent(
classLoadingConfig.parentFirstArtifacts().ifPresent(
parentFirstArtifacts -> {
for (String artifact : parentFirstArtifacts) {
parentFirstKeys.add(new GACT(artifact.split(":")));
Expand All @@ -891,18 +890,16 @@ private Set<ArtifactKey> getParentFirstKeys(CurateOutcomeBuildItem curateOutcome
return parentFirstKeys;
}

/**
* @return a {@code Set} containing the key of the artifacts to load from the parent ClassLoader first.
*/
private Set<ArtifactKey> getRemovedKeys(ClassLoadingConfig classLoadingConfig) {
final Set<ArtifactKey> removed = new HashSet<>();
classLoadingConfig.removedArtifacts.ifPresent(
removedArtifacts -> {
for (String artifact : removedArtifacts) {
removed.add(new GACT(artifact.split(":")));
}
});
return removed;
private Set<ArtifactKey> getRemovedArtifactKeys(ClassLoadingConfig classLoadingConfig) {
if (classLoadingConfig.removedArtifacts().isEmpty()) {
return Set.of();
}

Set<ArtifactKey> removedArtifacts = new HashSet<>();
for (String artifact : classLoadingConfig.removedArtifacts().get()) {
removedArtifacts.add(GACT.fromString(artifact));
}
return Collections.unmodifiableSet(removedArtifacts);
}

private void copyDependency(Set<ArtifactKey> parentFirstArtifacts, OutputTargetBuildItem outputTargetBuildItem,
Expand Down Expand Up @@ -1044,16 +1041,13 @@ private NativeImageSourceJarBuildItem buildNativeImageThinJar(CurateOutcomeBuild

log.info("Building native image source jar: " + runnerJar);

final Set<ArtifactKey> 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<String> 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()
Expand All @@ -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);
Expand Down Expand Up @@ -1109,7 +1103,7 @@ private void doLegacyThinJarGeneration(CurateOutcomeBuildItem curateOutcomeBuild
List<GeneratedClassBuildItem> allClasses,
FileSystem runnerZipFs,
MainClassBuildItem mainClassBuildItem,
ClassLoadingConfig classLoadingConfig)
Set<ArtifactKey> removedArtifacts)
throws IOException {
final Map<String, String> seen = new HashMap<>();
final StringBuilder classPath = new StringBuilder();
Expand All @@ -1120,9 +1114,8 @@ private void doLegacyThinJarGeneration(CurateOutcomeBuildItem curateOutcomeBuild

Predicate<String> ignoredEntriesPredicate = getThinJarIgnoredEntriesPredicate(packageConfig);

final Set<ArtifactKey> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx

private Set<String> removedApplicationClasses(CurateOutcomeBuildItem curation, ClassLoadingConfig classLoadingConfig) {
ResolvedDependency appArtifact = curation.getApplicationModel().getAppArtifact();
Set<String> entry = classLoadingConfig.removedResources
Set<String> entry = classLoadingConfig.removedResources()
.get(appArtifact.getGroupId() + ":" + appArtifact.getArtifactId());
return entry != null ? entry : Collections.emptySet();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ TransformedClassesBuildItem handleClassTransformation(List<BytecodeTransformerBu
ExecutorService buildExecutor,
CuratedApplicationShutdownBuildItem shutdown)
throws ExecutionException, InterruptedException {
if (bytecodeTransformerBuildItems.isEmpty() && classLoadingConfig.removedResources.isEmpty()
if (bytecodeTransformerBuildItems.isEmpty() && classLoadingConfig.removedResources().isEmpty()
&& removedResourceBuildItems.isEmpty()) {
return new TransformedClassesBuildItem(Collections.emptyMap());
}
Expand Down Expand Up @@ -314,7 +314,7 @@ private void handleRemovedResources(ClassLoadingConfig classLoadingConfig, Curat
List<RemovedResourceBuildItem> 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<ArtifactKey, Set<String>> removed = new HashMap<>();
for (Map.Entry<String, Set<String>> entry : classLoadingConfig.removedResources.entrySet()) {
for (Map.Entry<String, Set<String>> entry : classLoadingConfig.removedResources().entrySet()) {
removed.put(new GACT(entry.getKey().split(":")), entry.getValue());
}
for (RemovedResourceBuildItem i : removedResourceBuildItems) {
Expand Down

0 comments on commit 8a6fc13

Please sign in to comment.