diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java index 43a6b4647ff264..7de54b7a4acf31 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java @@ -535,7 +535,8 @@ private Map initDecoratedMethods() { Map candidates = new HashMap<>(); addDecoratedMethods(candidates, target.get().asClass(), bound, - new SubclassSkipPredicate(beanDeployment.getAssignabilityCheck()::isAssignableFrom)); + new SubclassSkipPredicate(beanDeployment.getAssignabilityCheck()::isAssignableFrom, + beanDeployment.getBeanArchiveIndex())); Map decoratedMethods = new HashMap<>(candidates.size()); for (Entry entry : candidates.entrySet()) { diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Methods.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Methods.java index fea42a8b7725af..1f859fc88c0e51 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Methods.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Methods.java @@ -161,7 +161,9 @@ static Set addInterceptedMethodCandidates(BeanDeployment beanDeploym boolean transformUnproxyableClasses) { return addInterceptedMethodCandidates(beanDeployment, classInfo, candidates, classLevelBindings, bytecodeTransformerConsumer, transformUnproxyableClasses, - new SubclassSkipPredicate(beanDeployment.getAssignabilityCheck()::isAssignableFrom), false); + new SubclassSkipPredicate(beanDeployment.getAssignabilityCheck()::isAssignableFrom, + beanDeployment.getBeanArchiveIndex()), + false); } static Set addInterceptedMethodCandidates(BeanDeployment beanDeployment, ClassInfo classInfo, @@ -454,12 +456,14 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str static class SubclassSkipPredicate implements Predicate { private final BiFunction assignableFromFun; + private final IndexView beanArchiveIndex; private ClassInfo clazz; private List regularMethods; private Set bridgeMethods = new HashSet<>(); - public SubclassSkipPredicate(BiFunction assignableFromFun) { + public SubclassSkipPredicate(BiFunction assignableFromFun, IndexView beanArchiveIndex) { this.assignableFromFun = assignableFromFun; + this.beanArchiveIndex = beanArchiveIndex; } void startProcessing(ClassInfo clazz) { @@ -505,6 +509,20 @@ public boolean test(MethodInfo method) { // Do not skip default methods - public non-abstract instance methods declared in an interface return false; } + + List parameters = method.parameters(); + if (!parameters.isEmpty() && (beanArchiveIndex != null)) { + for (Type type : parameters) { + ClassInfo parameterClassInfo = beanArchiveIndex.getClassByName(type.name()); + if (parameterClassInfo == null) { + continue; // hope for the best + } + if (!Modifier.isPublic(parameterClassInfo.flags())) { + return true; // if the parameter is not public, we end up with IllegalAccessError when trying to access the use the load the class + } + } + } + // Note that we intentionally do not skip final methods here - these are handled later return false; } diff --git a/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/SubclassSkipPredicateTest.java b/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/SubclassSkipPredicateTest.java index c7b0cb88cd9391..511cd8f78fe06b 100644 --- a/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/SubclassSkipPredicateTest.java +++ b/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/SubclassSkipPredicateTest.java @@ -21,7 +21,7 @@ public class SubclassSkipPredicateTest { public void testPredicate() throws IOException { IndexView index = Basics.index(Base.class, Submarine.class, Long.class, Number.class); AssignabilityCheck assignabilityCheck = new AssignabilityCheck(index, null); - SubclassSkipPredicate predicate = new SubclassSkipPredicate(assignabilityCheck::isAssignableFrom); + SubclassSkipPredicate predicate = new SubclassSkipPredicate(assignabilityCheck::isAssignableFrom, null); ClassInfo submarineClass = index.getClassByName(DotName.createSimple(Submarine.class.getName())); predicate.startProcessing(submarineClass); diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/methodargs/ExampleResource.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/methodargs/ExampleResource.java new file mode 100644 index 00000000000000..f0aac8de276f88 --- /dev/null +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/methodargs/ExampleResource.java @@ -0,0 +1,27 @@ +package io.quarkus.arc.test.interceptors.methodargs; + +import java.util.List; +import javax.inject.Singleton; + +@Singleton +@Simple +public class ExampleResource { + + // Just to try to confuse our bridge method impl. algorithm + public String create(List strings) { + return String.join(",", strings); + } + + String otherCreate(NotPublic notPublic) { + return notPublic.toString(); + } + + static class NotPublic { + + @Override + public String toString() { + return "NotPublic{}"; + } + } + +} diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/methodargs/MethodArgsInterceptionTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/methodargs/MethodArgsInterceptionTest.java new file mode 100644 index 00000000000000..ea3ffa024323b4 --- /dev/null +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/methodargs/MethodArgsInterceptionTest.java @@ -0,0 +1,34 @@ +package io.quarkus.arc.test.interceptors.methodargs; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import io.quarkus.arc.Arc; +import io.quarkus.arc.ArcContainer; +import io.quarkus.arc.test.ArcTestContainer; +import io.quarkus.arc.test.interceptors.Counter; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class MethodArgsInterceptionTest { + + @RegisterExtension + public ArcTestContainer container = new ArcTestContainer(Simple.class, SimpleInterceptor.class, ExampleResource.class, + Counter.class); + + @Test + public void testInterception() { + ArcContainer container = Arc.container(); + Counter counter = container.instance(Counter.class).get(); + + counter.reset(); + ExampleResource exampleResource = container.instance(ExampleResource.class).get(); + + assertEquals("first,second", exampleResource.create(List.of("first", "second"))); + assertEquals(1, counter.get()); + + assertEquals("NotPublic{}", exampleResource.otherCreate(new ExampleResource.NotPublic())); + assertEquals(1, counter.get()); // the interceptor should not have been called because the method argument is not public + } + +} diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/methodargs/Simple.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/methodargs/Simple.java new file mode 100644 index 00000000000000..04878c01a10a98 --- /dev/null +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/methodargs/Simple.java @@ -0,0 +1,18 @@ +package io.quarkus.arc.test.interceptors.methodargs; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import javax.interceptor.InterceptorBinding; + +@Target({ TYPE, METHOD }) +@Retention(RUNTIME) +@Documented +@InterceptorBinding +public @interface Simple { + +} diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/methodargs/SimpleInterceptor.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/methodargs/SimpleInterceptor.java new file mode 100644 index 00000000000000..d0c3d0eed7f145 --- /dev/null +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/methodargs/SimpleInterceptor.java @@ -0,0 +1,23 @@ +package io.quarkus.arc.test.interceptors.methodargs; + +import io.quarkus.arc.test.interceptors.Counter; +import javax.annotation.Priority; +import javax.inject.Inject; +import javax.interceptor.AroundInvoke; +import javax.interceptor.Interceptor; +import javax.interceptor.InvocationContext; + +@Simple +@Priority(1) +@Interceptor +public class SimpleInterceptor { + + @Inject + Counter counter; + + @AroundInvoke + Object mySuperCoolAroundInvoke(InvocationContext ctx) throws Exception { + counter.incrementAndGet(); + return ctx.proceed(); + } +}