Skip to content

Commit

Permalink
Merge pull request #37083 from Ladicek/arc-bce-fixes
Browse files Browse the repository at this point in the history
ArC: fix some corner cases in Build Compatible Extensions
  • Loading branch information
Ladicek authored Dec 1, 2023
2 parents 8c08a65 + 3129506 commit 37c57c6
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ BeanRegistrar.RegistrationContext registerBeans(List<BeanRegistrar> beanRegistra
buildContext.putInternal(Key.INJECTION_POINTS, Collections.unmodifiableList(this.injectionPoints));

if (buildCompatibleExtensions != null) {
buildCompatibleExtensions.runRegistration(beanArchiveComputingIndex, beans, observers);
buildCompatibleExtensions.runRegistration(beanArchiveComputingIndex, beans, interceptors, observers);
}

return registerSyntheticBeans(beanRegistrars, buildContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public boolean isAlternative() {

@Override
public Integer priority() {
return arcBeanInfo.getAlternativePriority();
return arcBeanInfo.getPriority();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ private List<org.jboss.jandex.ClassInfo> allSupertypes() {
alreadySeen.add(clazz.name());

DotName superClassName = clazz.superName();
if (!DotNames.OBJECT.equals(superClassName)) {
if (superClassName != null && !DotNames.OBJECT.equals(superClassName)) {
org.jboss.jandex.ClassInfo superClass = jandexIndex.getClassByName(superClassName);
workQueue.add(superClass);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import jakarta.interceptor.Interceptor;

import org.jboss.jandex.DotName;
import org.jboss.jandex.JandexReflection;

// only this class uses reflection, everything else in this package is reflection-free
class ExtensionInvoker {
Expand Down Expand Up @@ -83,43 +84,8 @@ void callExtensionMethod(ExtensionMethod method, List<Object> arguments)
throws ReflectiveOperationException {

Class<?>[] parameterTypes = new Class[arguments.size()];

for (int i = 0; i < parameterTypes.length; i++) {
Object argument = arguments.get(i);
Class<?> argumentClass = argument.getClass();

// beware of ordering! subtypes must precede supertypes
if (jakarta.enterprise.lang.model.declarations.ClassInfo.class.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.lang.model.declarations.ClassInfo.class;
} else if (jakarta.enterprise.lang.model.declarations.MethodInfo.class.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.lang.model.declarations.MethodInfo.class;
} else if (jakarta.enterprise.lang.model.declarations.FieldInfo.class.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.lang.model.declarations.FieldInfo.class;
} else if (jakarta.enterprise.inject.build.compatible.spi.ScannedClasses.class.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.inject.build.compatible.spi.ScannedClasses.class;
} else if (jakarta.enterprise.inject.build.compatible.spi.MetaAnnotations.class.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.inject.build.compatible.spi.MetaAnnotations.class;
} else if (jakarta.enterprise.inject.build.compatible.spi.ClassConfig.class.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.inject.build.compatible.spi.ClassConfig.class;
} else if (jakarta.enterprise.inject.build.compatible.spi.MethodConfig.class.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.inject.build.compatible.spi.MethodConfig.class;
} else if (jakarta.enterprise.inject.build.compatible.spi.FieldConfig.class.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.inject.build.compatible.spi.FieldConfig.class;
} else if (jakarta.enterprise.inject.build.compatible.spi.BeanInfo.class.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.inject.build.compatible.spi.BeanInfo.class;
} else if (jakarta.enterprise.inject.build.compatible.spi.ObserverInfo.class.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.inject.build.compatible.spi.ObserverInfo.class;
} else if (jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents.class
.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents.class;
} else if (jakarta.enterprise.inject.build.compatible.spi.Messages.class.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.inject.build.compatible.spi.Messages.class;
} else if (jakarta.enterprise.inject.build.compatible.spi.Types.class.isAssignableFrom(argumentClass)) {
parameterTypes[i] = jakarta.enterprise.inject.build.compatible.spi.Types.class;
} else {
// should never happen, internal error (or missing error handling) if it does
throw new IllegalArgumentException("Unexpected extension method argument: " + argument);
}
parameterTypes[i] = JandexReflection.loadRawType(method.parameterType(i));
}

Class<?> extensionClass = extensionClasses.get(method.extensionClass.name().toString());
Expand All @@ -136,7 +102,6 @@ void invalidate() {
}

/**
*
* @return {@code true} if no {@link BuildCompatibleExtension} was found, {@code false} otherwise
*/
boolean isEmpty() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ List<org.jboss.jandex.Type> parameterTypes() {
return jandex.parameterTypes();
}

org.jboss.jandex.Type parameterType(int index) {
return jandex.parameterType(index);
}

@Override
public String toString() {
return jandex.declaringClass().simpleName() + "." + jandex.name() + "()";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,30 @@
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import jakarta.enterprise.inject.build.compatible.spi.BeanInfo;
import jakarta.enterprise.inject.build.compatible.spi.ObserverInfo;
import jakarta.enterprise.inject.spi.DefinitionException;

import org.jboss.jandex.IndexView;

import io.quarkus.arc.processor.InterceptorInfo;

class ExtensionPhaseRegistration extends ExtensionPhaseBase {
private final AllAnnotationOverlays annotationOverlays;
private final Collection<io.quarkus.arc.processor.BeanInfo> allBeans;
private final Collection<io.quarkus.arc.processor.InterceptorInfo> allInterceptors;
private final Collection<io.quarkus.arc.processor.ObserverInfo> allObservers;
private final io.quarkus.arc.processor.AssignabilityCheck assignability;

ExtensionPhaseRegistration(ExtensionInvoker invoker, org.jboss.jandex.IndexView beanArchiveIndex, SharedErrors errors,
ExtensionPhaseRegistration(ExtensionInvoker invoker, IndexView beanArchiveIndex, SharedErrors errors,
AllAnnotationOverlays annotationOverlays, Collection<io.quarkus.arc.processor.BeanInfo> allBeans,
Collection<io.quarkus.arc.processor.ObserverInfo> allObservers) {
Collection<InterceptorInfo> allInterceptors, Collection<io.quarkus.arc.processor.ObserverInfo> allObservers) {
super(ExtensionPhase.REGISTRATION, invoker, beanArchiveIndex, errors);
this.annotationOverlays = annotationOverlays;
this.allBeans = allBeans;
this.allInterceptors = allInterceptors;
this.allObservers = allObservers;
this.assignability = new io.quarkus.arc.processor.AssignabilityCheck(beanArchiveIndex, null);
}
Expand Down Expand Up @@ -84,7 +91,7 @@ private Set<org.jboss.jandex.Type> expectedTypes(org.jboss.jandex.MethodInfo jan

private List<BeanInfo> matchingBeans(org.jboss.jandex.MethodInfo jandexMethod, boolean onlyInterceptors) {
Set<org.jboss.jandex.Type> expectedTypes = expectedTypes(jandexMethod);
return allBeans.stream()
return Stream.concat(allBeans.stream(), allInterceptors.stream())
.filter(bean -> {
if (onlyInterceptors && !bean.isInterceptor()) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ public void runEnhancement(org.jboss.jandex.IndexView beanArchiveIndex, BeanProc
*/
public void runRegistration(org.jboss.jandex.IndexView beanArchiveIndex,
Collection<io.quarkus.arc.processor.BeanInfo> allBeans,
Collection<io.quarkus.arc.processor.InterceptorInfo> allInterceptors,
Collection<io.quarkus.arc.processor.ObserverInfo> allObservers) {
if (invoker.isEmpty()) {
return;
Expand All @@ -282,7 +283,7 @@ public void runRegistration(org.jboss.jandex.IndexView beanArchiveIndex,

try {
new ExtensionPhaseRegistration(invoker, beanArchiveIndex, errors, annotationOverlays,
allBeans, allObservers).run();
allBeans, allInterceptors, allObservers).run();
} finally {
BuildServicesImpl.reset();
}
Expand Down Expand Up @@ -581,7 +582,7 @@ public void runRegistrationAgain(org.jboss.jandex.IndexView beanArchiveIndex,

try {
new ExtensionPhaseRegistration(invoker, beanArchiveIndex, errors, annotationOverlays,
syntheticBeans, syntheticObservers).run();
syntheticBeans, Collections.emptyList(), syntheticObservers).run();
} finally {
BuildServicesImpl.reset();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,30 @@

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.atomic.AtomicInteger;

import jakarta.annotation.Priority;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.Initialized;
import jakarta.enterprise.event.Observes;
import jakarta.enterprise.inject.Produces;
import jakarta.enterprise.inject.build.compatible.spi.BeanInfo;
import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension;
import jakarta.enterprise.inject.build.compatible.spi.InterceptorInfo;
import jakarta.enterprise.inject.build.compatible.spi.Messages;
import jakarta.enterprise.inject.build.compatible.spi.ObserverInfo;
import jakarta.enterprise.inject.build.compatible.spi.Registration;
import jakarta.enterprise.inject.build.compatible.spi.Types;
import jakarta.inject.Qualifier;
import jakarta.inject.Singleton;
import jakarta.interceptor.AroundInvoke;
import jakarta.interceptor.Interceptor;
import jakarta.interceptor.InterceptorBinding;
import jakarta.interceptor.InvocationContext;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand All @@ -26,7 +35,8 @@
public class RegistrationTest {
@RegisterExtension
public ArcTestContainer container = ArcTestContainer.builder()
.beanClasses(MyQualifier.class, MyService.class, MyFooService.class, MyBarService.class, MyBarServiceProducer.class)
.beanClasses(MyQualifier.class, MyInterceptorBinding.class, MyInterceptor.class, MyService.class,
MyFooService.class, MyBarService.class, MyBarServiceProducer.class)
.buildCompatibleExtensions(new MyExtension())
.build();

Expand All @@ -35,12 +45,14 @@ public void test() {
assertEquals(2, MyExtension.beanCounter.get());
assertEquals(1, MyExtension.beanMyQualifierCounter.get());
assertEquals(1, MyExtension.observerQualifierCounter.get());
assertEquals(2, MyExtension.interceptorCounter.get()); // one interceptor, counted twice
}

public static class MyExtension implements BuildCompatibleExtension {
static final AtomicInteger beanCounter = new AtomicInteger();
static final AtomicInteger beanMyQualifierCounter = new AtomicInteger();
static final AtomicInteger observerQualifierCounter = new AtomicInteger();
static final AtomicInteger interceptorCounter = new AtomicInteger();

@Registration(types = MyService.class)
public void beans(BeanInfo bean) {
Expand All @@ -57,6 +69,19 @@ public void observers(ObserverInfo observer, Types types) {
observerQualifierCounter.addAndGet(observer.qualifiers().size());
}
}

@Registration(types = MyInterceptor.class)
public void interceptors(InterceptorInfo interceptor) {
interceptorCounter.incrementAndGet();
}

@Registration(types = MyInterceptor.class)
public void interceptorsAsBeans(BeanInfo interceptor, Messages msg) {
if (!interceptor.isInterceptor()) {
msg.error("Interceptor expected", interceptor);
}
interceptorCounter.incrementAndGet();
}
}

// ---
Expand All @@ -66,6 +91,22 @@ public void observers(ObserverInfo observer, Types types) {
public @interface MyQualifier {
}

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@InterceptorBinding
public @interface MyInterceptorBinding {
}

@MyInterceptorBinding
@Interceptor
@Priority(1)
public static class MyInterceptor {
@AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception {
return ctx.proceed();
}
}

public interface MyService {
String hello();
}
Expand Down

0 comments on commit 37c57c6

Please sign in to comment.