From 08d13500f20a7d824ee292e36c945984b496ac1e Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Mon, 14 Aug 2023 16:20:16 +0200 Subject: [PATCH] ArC: fix StackOverflowError in AutoAddScopeBuildItem - if multiple conditions are used. (cherry picked from commit 1786eff1a3f0c6e7424be03392745ebe2c5d65cf) --- .../arc/deployment/AutoAddScopeBuildItem.java | 15 ++++++-- .../autoscope/AutoScopeBuildItemTest.java | 36 ++++++++++++++----- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/AutoAddScopeBuildItem.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/AutoAddScopeBuildItem.java index 805ef0aab7000..3de2e134b35ad 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/AutoAddScopeBuildItem.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/AutoAddScopeBuildItem.java @@ -77,7 +77,7 @@ public interface MatchPredicate { /** * @param clazz - * @param annotations + * @param annotations The current set of (possibly transformed) annotations * @param index * @return {@code true} if the input arguments match the predicate, * {@code false} otherwise @@ -85,10 +85,11 @@ public interface MatchPredicate { boolean test(ClassInfo clazz, Collection annotations, IndexView index); default MatchPredicate and(MatchPredicate other) { + MatchPredicate previous = this; return new MatchPredicate() { @Override public boolean test(ClassInfo clazz, Collection annotations, IndexView index) { - return test(clazz, annotations, index) && other.test(clazz, annotations, index); + return previous.test(clazz, annotations, index) && other.test(clazz, annotations, index); } }; } @@ -140,6 +141,8 @@ public Builder unremovable() { /** * Set a custom predicate. + *

+ * The previous predicate (if any) is replaced. * * @param predicate * @return self @@ -286,7 +289,13 @@ public Builder scopeAlreadyAdded(BiConsumer consumer) { return this; } - private Builder and(MatchPredicate other) { + /** + * The final predicate is a short-circuiting logical AND of the previous predicate (if any) and this condition. + * + * @param other + * @return self + */ + public Builder and(MatchPredicate other) { if (matchPredicate == null) { matchPredicate = other; } else { diff --git a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/autoscope/AutoScopeBuildItemTest.java b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/autoscope/AutoScopeBuildItemTest.java index 9212a428a2224..bf42fdc62815b 100644 --- a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/autoscope/AutoScopeBuildItemTest.java +++ b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/autoscope/AutoScopeBuildItemTest.java @@ -9,7 +9,9 @@ import jakarta.annotation.PostConstruct; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; +import jakarta.inject.Named; +import org.jboss.jandex.DotName; import org.jboss.logging.Logger; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -31,9 +33,11 @@ public class AutoScopeBuildItemTest { b.addBuildStep(new BuildStep() { @Override public void execute(BuildContext context) { - context.produce(AutoAddScopeBuildItem.builder().match((clazz, annotations, index) -> { - return clazz.name().toString().equals(SimpleBean.class.getName()); - }).defaultScope(BuiltinScope.DEPENDENT) + context.produce(AutoAddScopeBuildItem.builder() + .match((clazz, annotations, index) -> { + return clazz.name().toString().equals(SimpleBean.class.getName()); + }) + .defaultScope(BuiltinScope.DEPENDENT) .scopeAlreadyAdded((scope, reason) -> { // We can't pass the state directly to AutoScopeBuildItemTest because it's loaded by a different classloader Logger.getLogger("AutoScopeBuildItemTest").info(scope + ":" + reason); @@ -43,17 +47,30 @@ public void execute(BuildContext context) { b.addBuildStep(new BuildStep() { @Override public void execute(BuildContext context) { - context.produce(AutoAddScopeBuildItem.builder().match((clazz, annotations, index) -> { - return clazz.name().toString().equals(SimpleBean.class.getName()); - }).defaultScope(BuiltinScope.SINGLETON).priority(10).reason("Foo!").build()); + context.produce(AutoAddScopeBuildItem.builder() + .match((clazz, annotations, index) -> { + return clazz.name().toString().equals(SimpleBean.class.getName()); + }) + .anyMethodMatches(m -> m.hasAnnotation(PostConstruct.class)) + .isAnnotatedWith(DotName.createSimple(Named.class)) + .defaultScope(BuiltinScope.SINGLETON) + .priority(10) + .reason("Foo!") + .build()); } }).produces(AutoAddScopeBuildItem.class).build(); b.addBuildStep(new BuildStep() { @Override public void execute(BuildContext context) { - context.produce(AutoAddScopeBuildItem.builder().match((clazz, annotations, index) -> { - return clazz.name().toString().equals(NotABean.class.getName()); - }).defaultScope(BuiltinScope.SINGLETON).unremovable().build()); + context.produce(AutoAddScopeBuildItem.builder() + .match((clazz, annotations, index) -> { + return clazz.name().toString().equals(NotABean.class.getName()); + }) + .containsAnnotations(DotName.createSimple(PostConstruct.class)) + .and((clazz, annotations, index) -> annotations.isEmpty()) + .defaultScope(BuiltinScope.SINGLETON) + .unremovable() + .build()); } }).produces(AutoAddScopeBuildItem.class).build(); }).setLogRecordPredicate(log -> "AutoScopeBuildItemTest".equals(log.getLoggerName())) @@ -76,6 +93,7 @@ public void testBeans() { assertEquals(notABean1.ping(), Arc.container().instance(NotABean.class).get().ping()); } + @Named static class SimpleBean { private String id;