Skip to content

Commit

Permalink
Arc - Validate whether interceptors declare producer methods
Browse files Browse the repository at this point in the history
  • Loading branch information
manovotn committed Feb 22, 2023
1 parent 181dae5 commit b3671d1
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
import java.util.List;
import java.util.Set;

import jakarta.enterprise.inject.spi.DefinitionException;
import jakarta.enterprise.inject.spi.InterceptionType;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.FieldInfo;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.Type;
import org.jboss.jandex.Type.Kind;
Expand Down Expand Up @@ -57,6 +59,12 @@ public class InterceptorInfo extends BeanInfo implements Comparable<InterceptorI
if (Modifier.isStatic(method.flags())) {
continue;
}
if (method.hasAnnotation(DotNames.PRODUCES) || method.hasAnnotation(DotNames.DISPOSES)) {
// according to spec, finding @Produces or @Disposes on a method is a DefinitionException
throw new DefinitionException(
"An interceptor method cannot be marked @Produces or @Disposes - " + method + " in class: "
+ aClass);
}
if (method.hasAnnotation(DotNames.AROUND_INVOKE)) {
aroundInvokes.add(validateSignature(method));
}
Expand All @@ -71,6 +79,14 @@ public class InterceptorInfo extends BeanInfo implements Comparable<InterceptorI
}
}

for (FieldInfo field : aClass.fields()) {
if (field.hasAnnotation(DotNames.PRODUCES)) {
// according to spec, finding @Produces on a field is a DefinitionException
throw new DefinitionException(
"An interceptor field cannot be marked @Produces - " + field + " in class: " + aClass);
}
}

DotName superTypeName = aClass.superName();
aClass = superTypeName == null || DotNames.OBJECT.equals(superTypeName) ? null
: getClassByName(beanDeployment.getBeanArchiveIndex(), superTypeName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package io.quarkus.arc.test.producer.disposer.illegal;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import jakarta.annotation.Priority;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Disposes;
import jakarta.enterprise.inject.spi.DefinitionException;
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;

import io.quarkus.arc.test.ArcTestContainer;

public class DisposerInInterceptorTest {
@RegisterExtension
public ArcTestContainer container = ArcTestContainer.builder()
.beanClasses(BadInterceptor.class, FooBean.class, MyBinding.class).shouldFail()
.build();

@Test
public void testFailure() {
Throwable error = container.getFailure();
assertNotNull(error);
assertTrue(error instanceof DefinitionException);
}

@Interceptor
@MyBinding
@Priority(1)
static class BadInterceptor {

@AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
return ic.proceed();
}

// declaring a disposer inside an interceptor should raise DefinitionException
void dispose(@Disposes String ignored) {
}

}

@Dependent
@MyBinding
static class FooBean {

public String ping() {
return FooBean.class.getSimpleName();
}

}

@Target({ TYPE, METHOD })
@Retention(RUNTIME)
@Documented
@InterceptorBinding
@interface MyBinding {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package io.quarkus.arc.test.producer.illegal;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import jakarta.annotation.Priority;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Produces;
import jakarta.enterprise.inject.spi.DefinitionException;
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;

import io.quarkus.arc.test.ArcTestContainer;

public class ProducerFieldInInterceptorTest {

@RegisterExtension
public ArcTestContainer container = ArcTestContainer.builder()
.beanClasses(BadInterceptor.class, FooBean.class, MyBinding.class).shouldFail()
.build();

@Test
public void testFailure() {
Throwable error = container.getFailure();
assertNotNull(error);
assertTrue(error instanceof DefinitionException);
}

@Interceptor
@MyBinding
@Priority(1)
static class BadInterceptor {

@AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
return ic.proceed();
}

// declaring a producer inside an interceptor should raise DefinitionException
@Produces
String val = "42";
}

@Dependent
@MyBinding
static class FooBean {

public String ping() {
return ProducerMethodInInterceptorTest.FooBean.class.getSimpleName();
}

}

@Target({ TYPE, METHOD })
@Retention(RUNTIME)
@Documented
@InterceptorBinding
@interface MyBinding {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package io.quarkus.arc.test.producer.illegal;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import jakarta.annotation.Priority;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Produces;
import jakarta.enterprise.inject.spi.DefinitionException;
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;

import io.quarkus.arc.test.ArcTestContainer;

public class ProducerMethodInInterceptorTest {

@RegisterExtension
public ArcTestContainer container = ArcTestContainer.builder()
.beanClasses(BadInterceptor.class, FooBean.class, MyBinding.class).shouldFail()
.build();

@Test
public void testFailure() {
Throwable error = container.getFailure();
assertNotNull(error);
assertTrue(error instanceof DefinitionException);
}

@Interceptor
@MyBinding
@Priority(1)
static class BadInterceptor {

@AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
return ic.proceed();
}

// declaring a producer inside an interceptor should raise DefinitionException
@Produces
String generateString() {
return "42";
}

}

@Dependent
@MyBinding
static class FooBean {

public String ping() {
return FooBean.class.getSimpleName();
}

}

@Target({ TYPE, METHOD })
@Retention(RUNTIME)
@Documented
@InterceptorBinding
@interface MyBinding {

}
}

0 comments on commit b3671d1

Please sign in to comment.