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 151a73cfe28540..52363375b5c4c2 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 @@ -7,6 +7,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; +import java.util.Collections; +import java.util.Set; import org.jboss.jandex.Index; import org.jboss.jandex.Indexer; @@ -15,14 +17,19 @@ import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.builditem.ApplicationIndexBuildItem; import io.quarkus.deployment.builditem.ArchiveRootBuildItem; +import io.quarkus.deployment.configuration.ClassLoadingConfig; +import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem; +import io.quarkus.maven.dependency.ResolvedDependency; public class ApplicationIndexBuildStep { private static final Logger log = Logger.getLogger(ApplicationIndexBuildStep.class); @BuildStep - ApplicationIndexBuildItem build(ArchiveRootBuildItem root) throws IOException { + ApplicationIndexBuildItem build(ArchiveRootBuildItem root, CurateOutcomeBuildItem curation, + ClassLoadingConfig classLoadingConfig) throws IOException { Indexer indexer = new Indexer(); + Set removedApplicationClasses = removedApplicationClasses(curation, classLoadingConfig); for (Path p : root.getRootDirectories()) { Files.walkFileTree(p, new FileVisitor() { @Override @@ -33,14 +40,33 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (file.getFileName().toString().endsWith(".class")) { - log.debugf("Indexing %s", file); - try (InputStream stream = Files.newInputStream(file)) { - indexer.index(stream); + if (isRemovedApplicationClass( + file.toString(), removedApplicationClasses)) { + log.debugf("File %s will not be indexed because the class has been configured as part of '%s'", + file, "quarkus.class-loading.removed-resources"); + } else { + log.debugf("Indexing %s", file); + try (InputStream stream = Files.newInputStream(file)) { + indexer.index(stream); + } } } return FileVisitResult.CONTINUE; } + private boolean isRemovedApplicationClass(String fileName, Set removedApplicationClasses) { + if (removedApplicationClasses.isEmpty()) { + return false; + } + String sanitizedFileName = (fileName.startsWith("/") ? fileName.substring(1) : fileName); + for (String removedApplicationClass : removedApplicationClasses) { + if (sanitizedFileName.endsWith(removedApplicationClass)) { + return true; + } + } + return false; + } + @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { return FileVisitResult.CONTINUE; @@ -56,4 +82,11 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx return new ApplicationIndexBuildItem(appIndex); } + private Set removedApplicationClasses(CurateOutcomeBuildItem curation, ClassLoadingConfig classLoadingConfig) { + ResolvedDependency appArtifact = curation.getApplicationModel().getAppArtifact(); + 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 c36fbdbbc4ce96..d9ab5a0d55fa6b 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 @@ -7,6 +7,7 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -32,6 +33,7 @@ import io.quarkus.bootstrap.BootstrapDebug; import io.quarkus.bootstrap.classloading.ClassPathElement; import io.quarkus.bootstrap.classloading.QuarkusClassLoader; +import io.quarkus.bootstrap.model.ApplicationModel; import io.quarkus.deployment.QuarkusClassVisitor; import io.quarkus.deployment.QuarkusClassWriter; import io.quarkus.deployment.annotations.BuildStep; @@ -280,7 +282,12 @@ private void handleRemovedResources(ClassLoadingConfig classLoadingConfig, Curat removed.computeIfAbsent(i.getArtifact(), k -> new HashSet<>()).addAll(i.getResources()); } if (!removed.isEmpty()) { - for (ResolvedDependency i : curateOutcomeBuildItem.getApplicationModel().getRuntimeDependencies()) { + ApplicationModel applicationModel = curateOutcomeBuildItem.getApplicationModel(); + Collection runtimeDependencies = applicationModel.getRuntimeDependencies(); + List allArtifacts = new ArrayList<>(runtimeDependencies.size() + 1); + allArtifacts.addAll(runtimeDependencies); + allArtifacts.add(applicationModel.getAppArtifact()); + for (ResolvedDependency i : allArtifacts) { Set filtered = removed.remove(i.getKey()); if (filtered != null) { for (Path path : i.getResolvedPaths()) { diff --git a/integration-tests/main/src/main/java/io/quarkus/it/rest/RemovedJaxRsApplication.java b/integration-tests/main/src/main/java/io/quarkus/it/rest/RemovedJaxRsApplication.java new file mode 100644 index 00000000000000..608a16672b605d --- /dev/null +++ b/integration-tests/main/src/main/java/io/quarkus/it/rest/RemovedJaxRsApplication.java @@ -0,0 +1,11 @@ +package io.quarkus.it.rest; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +/** + * This class is actually never used, because we configure Quarkus to remove it from Class Loading and build time indexing + */ +@ApplicationPath("unused") +public class RemovedJaxRsApplication extends Application { +} diff --git a/integration-tests/main/src/main/resources/application.properties b/integration-tests/main/src/main/resources/application.properties index 7631fcc4813c7b..a6e7df99951e96 100644 --- a/integration-tests/main/src/main/resources/application.properties +++ b/integration-tests/main/src/main/resources/application.properties @@ -53,4 +53,5 @@ quarkus.native.resources.excludes = **/unwanted.* quarkus.log.metrics.enabled=true quarkus.native.additional-build-args =-H:ReflectionConfigurationFiles=reflection-config.json -quarkus.class-loading.removed-resources."io.quarkus\:quarkus-integration-test-shared-library"=io/quarkus/it/shared/RemovedResource.class \ No newline at end of file +quarkus.class-loading.removed-resources."io.quarkus\:quarkus-integration-test-shared-library"=io/quarkus/it/shared/RemovedResource.class +quarkus.class-loading.removed-resources."io.quarkus\:quarkus-integration-test-main"=io/quarkus/it/rest/RemovedJaxRsApplication.class