diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcConfig.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcConfig.java index a4329145212ab5..72fd88468b7e4c 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcConfig.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcConfig.java @@ -50,6 +50,16 @@ public class ArcConfig { @ConfigItem(defaultValue = "true") public boolean autoInjectFields; + /** + * If set to true, Arc will transform the bytecode of beans containing methods that need to be proxyable + * but have been declared as final. The transformation is simply a matter of removing final. + * This ensures that a proxy can be created properly. + * If the value is set to false, then an exception is thrown at build time indicating + * that a proxy could not be created because a method was final. + */ + @ConfigItem(defaultValue = "true") + public boolean removeFinalForProxyableMethods; + public final boolean isRemoveUnusedBeansFieldValid() { return ALLOWED_REMOVE_UNUSED_BEANS_VALUES.contains(removeUnusedBeans.toLowerCase()); } diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcProcessor.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcProcessor.java index 483890b4c70c98..04426b90b38190 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcProcessor.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcProcessor.java @@ -9,6 +9,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -33,6 +34,7 @@ import io.quarkus.arc.processor.BeanInfo; import io.quarkus.arc.processor.BeanProcessor; import io.quarkus.arc.processor.BuiltinScope; +import io.quarkus.arc.processor.BytecodeTransformer; import io.quarkus.arc.processor.ContextConfigurator; import io.quarkus.arc.processor.ContextRegistrar; import io.quarkus.arc.processor.ReflectionRegistration; @@ -47,6 +49,7 @@ import io.quarkus.deployment.annotations.Record; import io.quarkus.deployment.builditem.ApplicationArchivesBuildItem; import io.quarkus.deployment.builditem.ApplicationClassPredicateBuildItem; +import io.quarkus.deployment.builditem.BytecodeTransformerBuildItem; import io.quarkus.deployment.builditem.ExecutorBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.deployment.builditem.GeneratedClassBuildItem; @@ -214,6 +217,7 @@ public boolean test(BeanInfo bean) { } }); } + builder.setRemoveFinalFromProxyableMethods(arcConfig.removeFinalForProxyableMethods); BeanProcessor beanProcessor = builder.build(); ContextRegistrar.RegistrationContext context = beanProcessor.registerCustomContexts(); @@ -239,7 +243,8 @@ public BeanRegistrationPhaseBuildItem registerBeans(ContextRegistrationPhaseBuil // PHASE 3 - initialize and validate the bean deployment @BuildStep public ValidationPhaseBuildItem validate(BeanRegistrationPhaseBuildItem beanRegistrationPhase, - List beanConfigurators) { + List beanConfigurators, + BuildProducer bytecodeTransformer) { for (BeanConfiguratorBuildItem beanConfigurator : beanConfigurators) { for (BeanConfigurator value : beanConfigurator.getValues()) { @@ -248,7 +253,12 @@ public ValidationPhaseBuildItem validate(BeanRegistrationPhaseBuildItem beanRegi } } - beanRegistrationPhase.getBeanProcessor().initialize(); + beanRegistrationPhase.getBeanProcessor().initialize(new Consumer() { + @Override + public void accept(BytecodeTransformer t) { + bytecodeTransformer.produce(new BytecodeTransformerBuildItem(t.getClassToTransform(), t.getVisitorFunction())); + } + }); return new ValidationPhaseBuildItem(beanRegistrationPhase.getBeanProcessor().validate(), beanRegistrationPhase.getBeanProcessor()); } @@ -364,4 +374,4 @@ public boolean test(T t) { return false; } } -} \ No newline at end of file +} diff --git a/extensions/security/deployment/src/test/java/io/quarkus/security/test/cdi/BeanWithSecuredFinalMethod.java b/extensions/security/deployment/src/test/java/io/quarkus/security/test/cdi/BeanWithSecuredFinalMethod.java new file mode 100644 index 00000000000000..bee22955535f49 --- /dev/null +++ b/extensions/security/deployment/src/test/java/io/quarkus/security/test/cdi/BeanWithSecuredFinalMethod.java @@ -0,0 +1,19 @@ +package io.quarkus.security.test.cdi; + +import javax.annotation.security.DenyAll; +import javax.annotation.security.RolesAllowed; +import javax.inject.Singleton; + +@Singleton +public class BeanWithSecuredFinalMethod { + + @RolesAllowed("admin") + public final String securedMethod() { + return "accessibleForAdminOnly"; + } + + @DenyAll + public final String otherSecuredMethod(String input) { + return "denied"; + } +} diff --git a/extensions/security/deployment/src/test/java/io/quarkus/security/test/cdi/SecurityAnnotationOnFinalMethodTest.java b/extensions/security/deployment/src/test/java/io/quarkus/security/test/cdi/SecurityAnnotationOnFinalMethodTest.java new file mode 100644 index 00000000000000..c5287848632799 --- /dev/null +++ b/extensions/security/deployment/src/test/java/io/quarkus/security/test/cdi/SecurityAnnotationOnFinalMethodTest.java @@ -0,0 +1,45 @@ +package io.quarkus.security.test.cdi; + +import static io.quarkus.security.test.cdi.SecurityTestUtils.assertFailureFor; +import static io.quarkus.security.test.cdi.SecurityTestUtils.assertSuccess; +import static io.quarkus.security.test.utils.IdentityMock.ADMIN; +import static io.quarkus.security.test.utils.IdentityMock.ANONYMOUS; +import static io.quarkus.security.test.utils.IdentityMock.USER; + +import javax.inject.Inject; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.security.ForbiddenException; +import io.quarkus.security.UnauthorizedException; +import io.quarkus.security.test.utils.AuthData; +import io.quarkus.security.test.utils.IdentityMock; +import io.quarkus.test.QuarkusUnitTest; + +public class SecurityAnnotationOnFinalMethodTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClasses(BeanWithSecuredFinalMethod.class, IdentityMock.class, + AuthData.class, SecurityTestUtils.class)); + + @Inject + BeanWithSecuredFinalMethod bean; + + @Test + public void shouldRestrictAccessToSpecificRole() { + assertFailureFor(() -> bean.securedMethod(), UnauthorizedException.class, ANONYMOUS); + assertSuccess(() -> bean.securedMethod(), "accessibleForAdminOnly", ADMIN); + } + + @Test + public void shouldFailToAccessCompletely() { + assertFailureFor(() -> bean.otherSecuredMethod("whatever"), UnauthorizedException.class, ANONYMOUS); + assertFailureFor(() -> bean.otherSecuredMethod("whatever"), ForbiddenException.class, USER, ADMIN); + } + +} diff --git a/extensions/security/deployment/src/test/java/io/quarkus/security/test/cdi/SecurityAnnotationOnFinalMethodWithDisableFinalRemovalTest.java b/extensions/security/deployment/src/test/java/io/quarkus/security/test/cdi/SecurityAnnotationOnFinalMethodWithDisableFinalRemovalTest.java new file mode 100644 index 00000000000000..aafe5e031393c8 --- /dev/null +++ b/extensions/security/deployment/src/test/java/io/quarkus/security/test/cdi/SecurityAnnotationOnFinalMethodWithDisableFinalRemovalTest.java @@ -0,0 +1,39 @@ +package io.quarkus.security.test.cdi; + +import static org.junit.jupiter.api.Assertions.fail; + +import javax.enterprise.inject.spi.DeploymentException; +import javax.inject.Inject; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.security.test.utils.AuthData; +import io.quarkus.security.test.utils.IdentityMock; +import io.quarkus.test.QuarkusUnitTest; + +public class SecurityAnnotationOnFinalMethodWithDisableFinalRemovalTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClasses(BeanWithSecuredFinalMethod.class, IdentityMock.class, + AuthData.class, SecurityTestUtils.class) + .addAsResource(new StringAsset( + "quarkus.arc.remove-final-for-proxyable-methods=false"), + "application.properties")) + .setExpectedException(DeploymentException.class); + + @Inject + BeanWithSecuredFinalMethod bean; + + @Test + public void test() { + // should never be executed since the application should not be built + fail(); + } + +} diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java index 11148f0bb3c113..af993182d193ae 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java @@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -88,11 +89,12 @@ public class BeanDeployment { private final Map> customContexts; private final Collection beanDefiningAnnotations; + private final boolean removeFinalForProxyableMethods; BeanDeployment(IndexView index, Collection additionalBeanDefiningAnnotations, List annotationTransformers) { this(index, additionalBeanDefiningAnnotations, annotationTransformers, Collections.emptyList(), Collections.emptyList(), - null, false, null, Collections.emptyMap(), Collections.emptyList()); + null, false, null, Collections.emptyMap(), Collections.emptyList(), false); } BeanDeployment(IndexView index, Collection additionalBeanDefiningAnnotations, @@ -101,7 +103,7 @@ public class BeanDeployment { Collection resourceAnnotations, BuildContextImpl buildContext, boolean removeUnusedBeans, List> unusedExclusions, Map> additionalStereotypes, - List bindingRegistrars) { + List bindingRegistrars, boolean removeFinalForProxyableMethods) { this.buildContext = buildContext; Set beanDefiningAnnotations = new HashSet<>(); if (additionalBeanDefiningAnnotations != null) { @@ -154,6 +156,7 @@ public class BeanDeployment { this.beanResolver = new BeanResolver(this); this.interceptorResolver = new InterceptorResolver(this); + this.removeFinalForProxyableMethods = removeFinalForProxyableMethods; } ContextRegistrar.RegistrationContext registerCustomContexts(List contextRegistrars) { @@ -203,19 +206,19 @@ BeanRegistrar.RegistrationContext registerBeans(List beanRegistra return registerSyntheticBeans(beanRegistrars, buildContext); } - void init() { + void init(Consumer bytecodeTransformerConsumer) { long start = System.currentTimeMillis(); // Collect dependency resolution errors List errors = new ArrayList<>(); for (BeanInfo bean : beans) { - bean.init(errors); + bean.init(errors, bytecodeTransformerConsumer, removeFinalForProxyableMethods); } for (ObserverInfo observer : observers) { observer.init(errors); } for (InterceptorInfo interceptor : interceptors) { - interceptor.init(errors); + interceptor.init(errors, bytecodeTransformerConsumer, removeFinalForProxyableMethods); } processErrors(errors); 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 beee4628749a34..8806d4c65fe6c6 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 @@ -398,7 +398,8 @@ void validate(List errors, List validators) } } - void init(List errors) { + void init(List errors, Consumer bytecodeTransformerConsumer, + boolean removeFinalForProxyableMethods) { for (Injection injection : injections) { for (InjectionPointInfo injectionPoint : injection.injectionPoints) { Beans.resolveInjectionPoint(beanDeployment, this, injectionPoint, errors); @@ -407,7 +408,7 @@ void init(List errors) { if (disposer != null) { disposer.init(errors); } - interceptedMethods.putAll(initInterceptedMethods(errors)); + interceptedMethods.putAll(initInterceptedMethods(errors, bytecodeTransformerConsumer, removeFinalForProxyableMethods)); if (errors.isEmpty()) { lifecycleInterceptors.putAll(initLifecycleInterceptors()); } @@ -425,7 +426,8 @@ protected String getType() { } } - private Map initInterceptedMethods(List errors) { + private Map initInterceptedMethods(List errors, + Consumer bytecodeTransformerConsumer, boolean removeFinalForProxyableMethods) { if (!isInterceptor() && isClassBean()) { Map interceptedMethods = new HashMap<>(); Map> candidates = new HashMap<>(); @@ -439,7 +441,7 @@ private Map initInterceptedMethods(List } Set finalMethods = Methods.addInterceptedMethodCandidates(beanDeployment, target.get().asClass(), - candidates, classLevelBindings); + candidates, classLevelBindings, bytecodeTransformerConsumer, removeFinalForProxyableMethods); if (!finalMethods.isEmpty()) { errors.add(new DeploymentException(String.format( "Intercepted methods of the bean %s may not be declared final:\n\t- %s", getBeanClass(), diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java index 206d0a1e1406fb..66358dfe3635b4 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java @@ -15,6 +15,7 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Collectors; import org.jboss.jandex.AnnotationInstance; @@ -29,7 +30,7 @@ *
    *
  1. {@link #registerCustomContexts()}
  2. *
  3. {@link #registerBeans()}
  4. - *
  5. {@link #initialize()}
  6. + *
  7. {@link #initialize(Consumer)}
  8. *
  9. {@link #validate()}
  10. *
  11. {@link #processValidationErrors(io.quarkus.arc.processor.BeanDeploymentValidator.ValidationContext)}
  12. *
  13. {@link #generateResources(ReflectionRegistration)}
  14. @@ -73,7 +74,8 @@ private BeanProcessor(String name, IndexView index, Collection beanDeploymentValidators, Predicate applicationClassPredicate, boolean unusedBeansRemovalEnabled, List> unusedExclusions, Map> additionalStereotypes, - List interceptorBindingRegistrars) { + List interceptorBindingRegistrars, + boolean removeFinalForProxyableMethods) { this.reflectionRegistration = reflectionRegistration; this.applicationClassPredicate = applicationClassPredicate; this.name = name; @@ -91,7 +93,7 @@ private BeanProcessor(String name, IndexView index, Collection bytecodeTransformerConsumer) { + beanDeployment.init(bytecodeTransformerConsumer); } public BeanDeploymentValidator.ValidationContext validate() { @@ -201,7 +203,12 @@ public BeanDeployment getBeanDeployment() { public BeanDeployment process() throws IOException { registerCustomContexts(); registerBeans(); - initialize(); + initialize(new Consumer() { + @Override + public void accept(BytecodeTransformer transformer) { + + } + }); ValidationContext validationContext = validate(); processValidationErrors(validationContext); generateResources(null); @@ -242,6 +249,8 @@ public boolean test(DotName dotName) { } }; + private boolean removeFinalForProxyableMethods; + public Builder setName(String name) { this.name = name; return this; @@ -353,12 +362,17 @@ public Builder addRemovalExclusion(Predicate exclusion) { return this; } + public Builder setRemoveFinalFromProxyableMethods(boolean removeFinalForProxyableMethods) { + this.removeFinalForProxyableMethods = removeFinalForProxyableMethods; + return this; + } + public BeanProcessor build() { return new BeanProcessor(name, index, additionalBeanDefiningAnnotations, output, sharedAnnotationLiterals, reflectionRegistration, annotationTransformers, injectionPointTransformers, resourceAnnotations, beanRegistrars, contextRegistrars, beanDeploymentValidators, applicationClassPredicate, removeUnusedBeans, removalExclusions, additionalStereotypes, - additionalInterceptorBindingRegistrars); + additionalInterceptorBindingRegistrars, removeFinalForProxyableMethods); } } diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BytecodeTransformer.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BytecodeTransformer.java new file mode 100644 index 00000000000000..ed939481d353ae --- /dev/null +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BytecodeTransformer.java @@ -0,0 +1,24 @@ +package io.quarkus.arc.processor; + +import java.util.function.BiFunction; +import org.objectweb.asm.ClassVisitor; + +public class BytecodeTransformer { + + final String classToTransform; + final BiFunction visitorFunction; + + public BytecodeTransformer(String classToTransform, + BiFunction visitorFunction) { + this.classToTransform = classToTransform; + this.visitorFunction = visitorFunction; + } + + public String getClassToTransform() { + return classToTransform; + } + + public BiFunction getVisitorFunction() { + return visitorFunction; + } +} 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 5a1e23d3837038..7167cd2610f246 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 @@ -2,13 +2,17 @@ import static io.quarkus.arc.processor.IndexClassLookupUtils.getClassByName; +import io.quarkus.gizmo.DescriptorUtils; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Consumer; import java.util.stream.Collectors; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.ClassInfo; @@ -18,6 +22,9 @@ import org.jboss.jandex.Type; import org.jboss.jandex.TypeVariable; import org.jboss.logging.Logger; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; /** * @@ -115,8 +122,11 @@ static boolean isObjectToString(MethodInfo method) { static Set addInterceptedMethodCandidates(BeanDeployment beanDeployment, ClassInfo classInfo, Map> candidates, - List classLevelBindings) { - Set finalMethods = new HashSet<>(); + List classLevelBindings, Consumer bytecodeTransformerConsumer, + boolean removeFinalForProxyableMethods) { + + Set methodsFromWhichToRemoveFinal = new HashSet<>(); + Set finalMethodsFoundAndNotChanged = new HashSet<>(); for (MethodInfo method : classInfo.methods()) { if (skipForSubclass(method)) { continue; @@ -134,21 +144,83 @@ static Set addInterceptedMethodCandidates(BeanDeployment beanDeploym } } if (!merged.isEmpty()) { + boolean addToCandidates = true; if (Modifier.isFinal(method.flags())) { - finalMethods.add(method); - } else { + if (removeFinalForProxyableMethods) { + methodsFromWhichToRemoveFinal.add(NameAndDescriptor.fromMethodInfo(method)); + } else { + addToCandidates = false; + finalMethodsFoundAndNotChanged.add(method); + } + } + if (addToCandidates) { candidates.computeIfAbsent(new Methods.MethodKey(method), key -> merged); } } } + if (!methodsFromWhichToRemoveFinal.isEmpty()) { + bytecodeTransformerConsumer.accept( + new BytecodeTransformer(classInfo.name().toString(), new BiFunction() { + @Override + public ClassVisitor apply(String s, ClassVisitor classVisitor) { + return new ClassVisitor(Opcodes.ASM7, classVisitor) { + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, + String[] exceptions) { + if (methodsFromWhichToRemoveFinal.contains(new NameAndDescriptor(name, descriptor))) { + access = access & (~Opcodes.ACC_FINAL); + } + return super.visitMethod(access, name, descriptor, signature, exceptions); + } + }; + } + })); + } if (classInfo.superClassType() != null) { ClassInfo superClassInfo = getClassByName(beanDeployment.getIndex(), classInfo.superName()); if (superClassInfo != null) { - finalMethods - .addAll(addInterceptedMethodCandidates(beanDeployment, superClassInfo, candidates, classLevelBindings)); + finalMethodsFoundAndNotChanged.addAll(addInterceptedMethodCandidates(beanDeployment, superClassInfo, candidates, + classLevelBindings, bytecodeTransformerConsumer, removeFinalForProxyableMethods)); + } + } + return finalMethodsFoundAndNotChanged; + } + + private static class NameAndDescriptor { + private final String name; + private final String descriptor; + + public NameAndDescriptor(String name, String descriptor) { + this.name = name; + this.descriptor = descriptor; + } + + public static NameAndDescriptor fromMethodInfo(MethodInfo method) { + String returnTypeDesc = DescriptorUtils.objectToDescriptor(method.returnType().name().toString()); + String[] paramTypesDesc = new String[(method.parameters().size())]; + for (int i = 0; i < method.parameters().size(); i++) { + paramTypesDesc[i] = DescriptorUtils.objectToDescriptor(method.parameters().get(i).name().toString()); } + + return new NameAndDescriptor(method.name(), + DescriptorUtils.methodSignatureToDescriptor(returnTypeDesc, paramTypesDesc)); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + NameAndDescriptor that = (NameAndDescriptor) o; + return name.equals(that.name) && + descriptor.equals(that.descriptor); + } + + @Override + public int hashCode() { + return Objects.hash(name, descriptor); } - return finalMethods; } private static boolean skipForSubclass(MethodInfo method) { diff --git a/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/TypesTest.java b/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/TypesTest.java index b47ed0a32a6b66..ddcbd139cdecff 100644 --- a/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/TypesTest.java +++ b/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/TypesTest.java @@ -38,7 +38,7 @@ public void testGetTypeClosure() throws IOException { Collections.emptyMap(), new BeanDeployment(index, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), null, - false, Collections.emptyList(), Collections.emptyMap(), Collections.emptyList()), + false, Collections.emptyList(), Collections.emptyMap(), Collections.emptyList(), false), resolvedTypeVariables::put); assertEquals(3, bazTypes.size()); assertTrue(bazTypes.contains(Type.create(bazName, Kind.CLASS))); @@ -55,7 +55,7 @@ public void testGetTypeClosure() throws IOException { Set fooTypes = Types.getClassBeanTypeClosure(fooClass, new BeanDeployment(index, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), null, - false, Collections.emptyList(), Collections.emptyMap(), Collections.emptyList())); + false, Collections.emptyList(), Collections.emptyMap(), Collections.emptyList(), false)); assertEquals(2, fooTypes.size()); for (Type t : fooTypes) { if (t.kind().equals(Kind.PARAMETERIZED_TYPE)) { @@ -71,7 +71,7 @@ public void testGetTypeClosure() throws IOException { Set producerMethodTypes = Types.getProducerMethodTypeClosure(producerMethod, new BeanDeployment(index, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), null, - false, Collections.emptyList(), Collections.emptyMap(), Collections.emptyList())); + false, Collections.emptyList(), Collections.emptyMap(), Collections.emptyList(), false)); assertEquals(1, producerMethodTypes.size()); // Object is the sole type @@ -79,7 +79,7 @@ public void testGetTypeClosure() throws IOException { Set producerFieldTypes = Types.getProducerFieldTypeClosure(producerField, new BeanDeployment(index, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), null, - false, Collections.emptyList(), Collections.emptyMap(), Collections.emptyList())); + false, Collections.emptyList(), Collections.emptyMap(), Collections.emptyList(), false)); assertEquals(1, producerFieldTypes.size()); }