From ede3b1a43d0692b6ced93d225aadcd660bd219ce Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Wed, 10 Jan 2024 16:48:20 +0100 Subject: [PATCH 1/4] WELD-2765 Update method invokers to latest spec proposal Use WeldInvokerBuilder API --- .../org/jboss/weld/bootstrap/Validator.java | 43 ++++++ .../events/AbstractProcessClassBean.java | 37 +++++ .../events/ProcessManagedBeanImpl.java | 10 -- .../events/ProcessSessionBeanImpl.java | 10 -- .../invokable/AbstractInvokerBuilder.java | 138 +++++++++++------- .../org/jboss/weld/invokable/ArrayUtils.java | 15 ++ .../weld/invokable/ConfiguredLookup.java | 20 +++ .../weld/invokable/InvokerBuilderImpl.java | 8 +- .../org/jboss/weld/invokable/InvokerImpl.java | 2 +- .../weld/invokable/InvokerInfoBuilder.java | 10 +- .../org/jboss/weld/invokable/LookupUtils.java | 42 ++++-- .../weld/invokable/MethodHandleUtils.java | 31 ++-- .../jboss/weld/invokable/PrimitiveUtils.java | 37 ----- .../jboss/weld/invokable/TargetMethod.java | 48 ++++++ .../jboss/weld/logging/ValidatorLogger.java | 11 ++ .../jboss/weld/manager/BeanManagerImpl.java | 38 ++++- .../weld/util/ForwardingBeanManager.java | 11 ++ .../weld/invokable/Playground_Spread.java | 15 +- .../weld/invokable/Playground_Wrapper.java | 3 +- pom.xml | 6 +- .../tests/invokable/BuildCompatExtension.java | 110 +++++++------- .../invokable/InvokableMethodBCETest.java | 14 +- .../tests/invokable/InvokableMethodTest.java | 14 +- .../tests/invokable/ObservingExtension.java | 99 +++++++------ .../invokable/common/InvocationWrapper.java | 3 +- .../tests/invokable/lookup/BeanProducer.java | 12 -- .../tests/invokable/lookup/InvokableBean.java | 10 -- .../lookup/InvokableMethodLookupTest.java | 29 +--- .../lookup/InvokerRegistreringExtension.java | 22 +-- .../ambiguous/AmbiguousLookupInvokerTest.java | 31 ++++ .../lookup/ambiguous/BeanProducer.java | 20 +++ .../lookup/ambiguous/InvokableBean.java | 12 ++ .../InvokerRegistreringExtension.java | 26 ++++ .../lookup/{ => ambiguous}/MyQualifier5.java | 2 +- .../lookup/unsatisfied/InvokableBean.java | 12 ++ .../InvokerRegistreringExtension.java | 26 ++++ .../UnsatisfiedLookupInvokerTest.java | 31 ++++ .../input/InputTransformerTest.java | 4 +- .../input/ObservingExtension.java | 17 ++- .../output/ObservingExtension.java | 21 +-- .../output/OutputTransformerTest.java | 4 +- .../extension/translator/BeanInfoImpl.java | 45 ------ .../extension/translator/ClassConfigImpl.java | 3 + .../translator/ExtensionInvoker.java | 41 +----- .../ExtensionMethodParameterType.java | 3 + .../ExtensionPhaseRegistration.java | 4 +- .../translator/InvokerFactoryImpl.java | 72 +++++++++ .../translator/ReflectionMembers.java | 12 +- .../extension/translator/SecurityActions.java | 20 +++ 49 files changed, 811 insertions(+), 443 deletions(-) create mode 100644 impl/src/main/java/org/jboss/weld/invokable/ArrayUtils.java create mode 100644 impl/src/main/java/org/jboss/weld/invokable/ConfiguredLookup.java delete mode 100644 impl/src/main/java/org/jboss/weld/invokable/PrimitiveUtils.java create mode 100644 impl/src/main/java/org/jboss/weld/invokable/TargetMethod.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/AmbiguousLookupInvokerTest.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/BeanProducer.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/InvokableBean.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/InvokerRegistreringExtension.java rename tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/{ => ambiguous}/MyQualifier5.java (77%) create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/unsatisfied/InvokableBean.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/unsatisfied/InvokerRegistreringExtension.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/unsatisfied/UnsatisfiedLookupInvokerTest.java create mode 100644 weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/InvokerFactoryImpl.java diff --git a/impl/src/main/java/org/jboss/weld/bootstrap/Validator.java b/impl/src/main/java/org/jboss/weld/bootstrap/Validator.java index 6ff603be1a..073b09b3a7 100644 --- a/impl/src/main/java/org/jboss/weld/bootstrap/Validator.java +++ b/impl/src/main/java/org/jboss/weld/bootstrap/Validator.java @@ -88,11 +88,14 @@ import org.jboss.weld.exceptions.DefinitionException; import org.jboss.weld.exceptions.DeploymentException; import org.jboss.weld.exceptions.UnproxyableResolutionException; +import org.jboss.weld.inject.WeldInstance; import org.jboss.weld.injection.producer.AbstractMemberProducer; import org.jboss.weld.injection.producer.BasicInjectionTarget; import org.jboss.weld.interceptor.reader.PlainInterceptorFactory; import org.jboss.weld.interceptor.spi.metadata.InterceptorClassMetadata; import org.jboss.weld.interceptor.spi.model.InterceptionModel; +import org.jboss.weld.invokable.AbstractInvokerBuilder; +import org.jboss.weld.invokable.ConfiguredLookup; import org.jboss.weld.literal.DecoratedLiteral; import org.jboss.weld.literal.InterceptedLiteral; import org.jboss.weld.logging.BeanLogger; @@ -499,6 +502,7 @@ public void validateDeployment(BeanManagerImpl manager, BeanDeployment deploymen validateDisposalMethods(deployment.getBeanDeployer().getEnvironment()); validateObserverMethods(deployment.getBeanDeployer().getEnvironment().getObservers(), manager); validateBeanNames(manager); + validateInvokers(manager); } public void validateSpecialization(BeanManagerImpl manager) { @@ -1030,6 +1034,45 @@ private static void validatePseudoScopedInjectionPoint(InjectionPoint ij, BeanMa } } + private void validateInvokers(BeanManagerImpl manager) { + List errors = new ArrayList<>(); + + WeldInstance instance = manager.createInstance(); + for (AbstractInvokerBuilder invoker : manager.getInvokers()) { + Class reflectionBeanClass = invoker.getBeanClass().getJavaClass(); + Method reflectionMethod = invoker.getMethod().getReflection(); + + for (ConfiguredLookup config : invoker.getConfiguredLookups()) { + WeldInstance lookup = instance.select(config.type, config.qualifiers); + if (lookup.isUnsatisfied()) { + if (config.isInstanceLookup()) { + errors.add(ValidatorLogger.LOG.invokerUnsatisfiedInstanceLookup( + reflectionBeanClass, reflectionMethod)); + } else { + errors.add(ValidatorLogger.LOG.invokerUnsatisfiedArgumentLookup( + reflectionBeanClass, reflectionMethod, config.position)); + } + } else if (lookup.isAmbiguous()) { + if (config.isInstanceLookup()) { + errors.add(ValidatorLogger.LOG.invokerAmbiguousInstanceLookup( + reflectionBeanClass, reflectionMethod)); + } else { + errors.add(ValidatorLogger.LOG.invokerAmbiguousArgumentLookup( + reflectionBeanClass, reflectionMethod, config.position)); + } + } + } + } + + manager.forgetInvokersAfterValidation(); + + if (errors.size() == 1) { + throw errors.get(0); + } else if (errors.size() > 1) { + throw new DeploymentException(errors); + } + } + @Override public void cleanup() { } diff --git a/impl/src/main/java/org/jboss/weld/bootstrap/events/AbstractProcessClassBean.java b/impl/src/main/java/org/jboss/weld/bootstrap/events/AbstractProcessClassBean.java index 52691029ad..4caf5e1ba9 100644 --- a/impl/src/main/java/org/jboss/weld/bootstrap/events/AbstractProcessClassBean.java +++ b/impl/src/main/java/org/jboss/weld/bootstrap/events/AbstractProcessClassBean.java @@ -16,12 +16,22 @@ */ package org.jboss.weld.bootstrap.events; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.lang.reflect.Type; import jakarta.enterprise.inject.spi.Annotated; +import jakarta.enterprise.inject.spi.AnnotatedMethod; +import jakarta.enterprise.inject.spi.Decorator; +import jakarta.enterprise.inject.spi.Interceptor; import jakarta.enterprise.inject.spi.ProcessBean; +import jakarta.enterprise.invoke.Invoker; +import jakarta.enterprise.invoke.InvokerBuilder; import org.jboss.weld.bean.ClassBean; +import org.jboss.weld.exceptions.DeploymentException; +import org.jboss.weld.invokable.InvokerBuilderImpl; +import org.jboss.weld.invokable.TargetMethod; import org.jboss.weld.manager.BeanManagerImpl; public abstract class AbstractProcessClassBean> extends AbstractDefinitionContainerEvent @@ -44,4 +54,31 @@ public B getBean() { return bean; } + public InvokerBuilder> createInvoker(AnnotatedMethod annotatedMethod) { + checkWithinObserverNotification(); + + ClassBean bean = getBean(); + if (bean instanceof Interceptor) { + throw new DeploymentException("Cannot build invoker for an interceptor: " + bean); + } + if (bean instanceof Decorator) { + throw new DeploymentException("Cannot build invoker for a decorator: " + bean); + } + + Method method = annotatedMethod.getJavaMember(); + if (Modifier.isPrivate(method.getModifiers())) { + throw new DeploymentException("Cannot build invoker for a private method: " + annotatedMethod); + } + if ("java.lang.Object".equals(method.getDeclaringClass().getName()) + && !"toString".equals(method.getName())) { + throw new DeploymentException("Cannot build invoker for a method declared on java.lang.Object: " + annotatedMethod); + } + + if (!bean.getAnnotated().getMethods().contains(annotatedMethod)) { + throw new DeploymentException("Method does not belong to bean " + bean + ": " + annotatedMethod); + } + + return new InvokerBuilderImpl<>(bean.getAnnotated(), new TargetMethod(annotatedMethod), getBeanManager()); + } + } diff --git a/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessManagedBeanImpl.java b/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessManagedBeanImpl.java index 3e75a69b5d..60614aeb06 100644 --- a/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessManagedBeanImpl.java +++ b/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessManagedBeanImpl.java @@ -18,14 +18,10 @@ import java.lang.reflect.Type; -import jakarta.enterprise.inject.spi.AnnotatedMethod; import jakarta.enterprise.inject.spi.AnnotatedType; import jakarta.enterprise.inject.spi.ProcessManagedBean; -import jakarta.enterprise.invoke.Invoker; -import jakarta.enterprise.invoke.InvokerBuilder; import org.jboss.weld.bean.ManagedBean; -import org.jboss.weld.invokable.InvokerBuilderImpl; import org.jboss.weld.manager.BeanManagerImpl; public class ProcessManagedBeanImpl extends AbstractProcessClassBean> implements ProcessManagedBean { @@ -46,10 +42,4 @@ public AnnotatedType getAnnotatedBeanClass() { return getBean().getAnnotated(); } - @Override - public InvokerBuilder> createInvoker(AnnotatedMethod annotatedMethod) { - checkWithinObserverNotification(); - return new InvokerBuilderImpl<>(getBean().getType(), annotatedMethod.getJavaMember(), getBeanManager()); - } - } diff --git a/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessSessionBeanImpl.java b/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessSessionBeanImpl.java index f499491fbc..494e306838 100644 --- a/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessSessionBeanImpl.java +++ b/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessSessionBeanImpl.java @@ -18,15 +18,11 @@ import java.lang.reflect.Type; -import jakarta.enterprise.inject.spi.AnnotatedMethod; import jakarta.enterprise.inject.spi.AnnotatedType; import jakarta.enterprise.inject.spi.ProcessSessionBean; import jakarta.enterprise.inject.spi.SessionBeanType; -import jakarta.enterprise.invoke.Invoker; -import jakarta.enterprise.invoke.InvokerBuilder; import org.jboss.weld.bean.SessionBean; -import org.jboss.weld.invokable.InvokerBuilderImpl; import org.jboss.weld.logging.BootstrapLogger; import org.jboss.weld.manager.BeanManagerImpl; @@ -67,10 +63,4 @@ public AnnotatedType getAnnotatedBeanClass() { return getBean().getAnnotated(); } - @Override - public InvokerBuilder> createInvoker(AnnotatedMethod annotatedMethod) { - checkWithinObserverNotification(); - return new InvokerBuilderImpl<>(getBean().getEjbDescriptor().getBeanClass(), annotatedMethod.getJavaMember(), - getBeanManager()); - } } diff --git a/impl/src/main/java/org/jboss/weld/invokable/AbstractInvokerBuilder.java b/impl/src/main/java/org/jboss/weld/invokable/AbstractInvokerBuilder.java index c480d3755c..8683592f38 100644 --- a/impl/src/main/java/org/jboss/weld/invokable/AbstractInvokerBuilder.java +++ b/impl/src/main/java/org/jboss/weld/invokable/AbstractInvokerBuilder.java @@ -5,19 +5,19 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Parameter; import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import jakarta.enterprise.inject.spi.AnnotatedType; import jakarta.enterprise.inject.spi.BeanManager; -import jakarta.enterprise.invoke.InvokerBuilder; -// TODO deployment-time validation of configured lookups -abstract class AbstractInvokerBuilder implements InvokerBuilder { +import org.jboss.weld.invoke.WeldInvokerBuilder; +import org.jboss.weld.manager.BeanManagerImpl; - final Class beanClass; - // work with reflection representation so that we can re-use this logic from within BCE - final Method method; +public abstract class AbstractInvokerBuilder implements WeldInvokerBuilder { + final AnnotatedType beanClass; + final TargetMethod method; boolean instanceLookup; boolean[] argLookup; @@ -29,35 +29,36 @@ abstract class AbstractInvokerBuilder implements InvokerBuilder { final BeanManager beanManager; - public AbstractInvokerBuilder(Class beanClass, Method method, BeanManager beanManager) { + AbstractInvokerBuilder(AnnotatedType beanClass, TargetMethod method, BeanManagerImpl beanManager) { this.beanClass = beanClass; this.method = method; this.argLookup = new boolean[method.getParameterCount()]; this.argTransformers = new TransformerMetadata[method.getParameterCount()]; this.beanManager = beanManager; + beanManager.addInvoker(this); } @Override - public InvokerBuilder setInstanceLookup() { + public WeldInvokerBuilder withInstanceLookup() { this.instanceLookup = true; return this; } @Override - public InvokerBuilder setArgumentLookup(int position) { - if (position >= argLookup.length) { - // TODO better exception - throw new IllegalArgumentException("Error attempting to set CDI argument lookup for arg number " + position - + " while the number of method args is " + argLookup.length); + public WeldInvokerBuilder withArgumentLookup(int position) { + if (position < 0 || position >= argLookup.length) { + // TODO better exception, use Logger interface + throw new IllegalArgumentException("Cannot lookup argument " + position + + ", the number of method parameters is " + argLookup.length); } argLookup[position] = true; return this; } @Override - public InvokerBuilder setInstanceTransformer(Class clazz, String methodName) { + public WeldInvokerBuilder withInstanceTransformer(Class clazz, String methodName) { if (instanceTransformer != null) { - // TODO better exception + // TODO better exception, use Logger interface throw new IllegalStateException("Instance transformer already set"); } this.instanceTransformer = new TransformerMetadata(clazz, methodName, TransformerType.INSTANCE); @@ -65,14 +66,14 @@ public InvokerBuilder setInstanceTransformer(Class clazz, String methodNam } @Override - public InvokerBuilder setArgumentTransformer(int position, Class clazz, String methodName) { - if (position >= argTransformers.length) { - // TODO better exception - throw new IllegalArgumentException("Error attempting to set an argument lookup. Number of method args: " - + argLookup.length + " arg position: " + position); + public WeldInvokerBuilder withArgumentTransformer(int position, Class clazz, String methodName) { + if (position < 0 || position >= argTransformers.length) { + // TODO better exception, use Logger interface + throw new IllegalArgumentException("Cannot transform argument " + position + + ", the number of method parameters is " + argLookup.length); } if (argTransformers[position] != null) { - // TODO better exception + // TODO better exception, use Logger interface throw new IllegalStateException("Argument transformer " + position + " already set"); } this.argTransformers[position] = new TransformerMetadata(clazz, methodName, TransformerType.ARGUMENT); @@ -80,9 +81,9 @@ public InvokerBuilder setArgumentTransformer(int position, Class clazz, St } @Override - public InvokerBuilder setReturnValueTransformer(Class clazz, String methodName) { + public WeldInvokerBuilder withReturnValueTransformer(Class clazz, String methodName) { if (returnValueTransformer != null) { - // TODO better exception + // TODO better exception, use Logger interface throw new IllegalStateException("Return value transformer already set"); } this.returnValueTransformer = new TransformerMetadata(clazz, methodName, TransformerType.RETURN_VALUE); @@ -90,9 +91,9 @@ public InvokerBuilder setReturnValueTransformer(Class clazz, String method } @Override - public InvokerBuilder setExceptionTransformer(Class clazz, String methodName) { + public WeldInvokerBuilder withExceptionTransformer(Class clazz, String methodName) { if (exceptionTransformer != null) { - // TODO better exception + // TODO better exception, use Logger interface throw new IllegalStateException("Exception transformer already set"); } this.exceptionTransformer = new TransformerMetadata(clazz, methodName, TransformerType.EXCEPTION); @@ -100,9 +101,9 @@ public InvokerBuilder setExceptionTransformer(Class clazz, String methodNa } @Override - public InvokerBuilder setInvocationWrapper(Class clazz, String methodName) { + public WeldInvokerBuilder withInvocationWrapper(Class clazz, String methodName) { if (invocationWrapper != null) { - // TODO better exception + // TODO better exception, use Logger interface throw new IllegalStateException("Invocation wrapper already set"); } this.invocationWrapper = new TransformerMetadata(clazz, methodName, TransformerType.WRAPPER); @@ -110,7 +111,7 @@ public InvokerBuilder setInvocationWrapper(Class clazz, String methodName) } private boolean requiresCleanup() { - boolean isStaticMethod = Modifier.isStatic(method.getModifiers()); + boolean isStaticMethod = method.isStatic(); if (instanceTransformer != null && !isStaticMethod) { return true; } @@ -131,19 +132,22 @@ private boolean requiresCleanup() { } InvokerImpl doBuild() { - boolean isStaticMethod = Modifier.isStatic(method.getModifiers()); + Class reflectionBeanClass = beanClass.getJavaClass(); + Method reflectionMethod = method.getReflection(); + + boolean isStaticMethod = method.isStatic(); int instanceArguments = isStaticMethod ? 0 : 1; boolean requiresCleanup = requiresCleanup(); - MethodHandle mh = MethodHandleUtils.createMethodHandle(method); + MethodHandle mh = MethodHandleUtils.createMethodHandle(reflectionMethod); // single, array-typed parameter at the end for variable arity methods mh = mh.asFixedArity(); // instance transformer if (instanceTransformer != null && !isStaticMethod) { - MethodHandle instanceTransformerMethod = MethodHandleUtils.createMethodHandleFromTransformer(method, - instanceTransformer, beanClass); + MethodHandle instanceTransformerMethod = MethodHandleUtils.createMethodHandleFromTransformer(reflectionMethod, + instanceTransformer, reflectionBeanClass); if (instanceTransformerMethod.type().parameterCount() == 1) { // no cleanup mh = MethodHandles.filterArguments(mh, 0, instanceTransformerMethod); } else if (instanceTransformerMethod.type().parameterCount() == 2) { // cleanup @@ -164,8 +168,8 @@ private boolean requiresCleanup() { continue; } int position = instanceArguments + i; - MethodHandle argTransformerMethod = MethodHandleUtils.createMethodHandleFromTransformer(method, - argTransformers[i], method.getParameterTypes()[i]); + MethodHandle argTransformerMethod = MethodHandleUtils.createMethodHandleFromTransformer(reflectionMethod, + argTransformers[i], reflectionMethod.getParameterTypes()[i]); if (argTransformerMethod.type().parameterCount() == 1) { // no cleanup mh = MethodHandles.filterArguments(mh, position, argTransformerMethod); } else if (argTransformerMethod.type().parameterCount() == 2) { // cleanup @@ -180,14 +184,14 @@ private boolean requiresCleanup() { // return type transformer if (returnValueTransformer != null) { - MethodHandle returnValueTransformerMethod = MethodHandleUtils.createMethodHandleFromTransformer(method, - returnValueTransformer, method.getReturnType()); + MethodHandle returnValueTransformerMethod = MethodHandleUtils.createMethodHandleFromTransformer(reflectionMethod, + returnValueTransformer, reflectionMethod.getReturnType()); mh = MethodHandles.filterReturnValue(mh, returnValueTransformerMethod); } // exception transformer if (exceptionTransformer != null) { - MethodHandle exceptionTransformerMethod = MethodHandleUtils.createMethodHandleFromTransformer(method, + MethodHandle exceptionTransformerMethod = MethodHandleUtils.createMethodHandleFromTransformer(reflectionMethod, exceptionTransformer, Throwable.class); mh = MethodHandles.catchException(mh, Throwable.class, exceptionTransformerMethod); } @@ -228,9 +232,9 @@ private boolean requiresCleanup() { // instance lookup if (instanceLookup && !isStaticMethod) { - Type type = beanClass; Class parameterType = typeBeforeLookups.parameterType(1); - Annotation[] qualifiers = LookupUtils.classQualifiers(beanClass, beanManager); + Type type = reflectionBeanClass; + Annotation[] qualifiers = LookupUtils.extractQualifiers(beanClass.getAnnotations(), beanManager); MethodHandle instanceLookupMethod = MethodHandleUtils.LOOKUP; instanceLookupMethod = MethodHandles.insertArguments(instanceLookupMethod, 1, beanManager, type, qualifiers); instanceLookupMethod = instanceLookupMethod.asType(instanceLookupMethod.type().changeReturnType(parameterType)); @@ -246,10 +250,9 @@ private boolean requiresCleanup() { continue; } int position = positionsBeforeArguments + i; - Parameter parameter = method.getParameters()[i]; - Type type = parameter.getParameterizedType(); Class parameterType = typeBeforeLookups.parameterType(i + (isStaticMethod ? 1 : 2)); - Annotation[] qualifiers = LookupUtils.parameterQualifiers(parameter, beanManager); + Type type = reflectionMethod.getParameters()[i].getParameterizedType(); + Annotation[] qualifiers = LookupUtils.extractQualifiers(method.getParameterAnnotations(i), beanManager); MethodHandle argumentLookupMethod = MethodHandleUtils.LOOKUP; argumentLookupMethod = MethodHandles.insertArguments(argumentLookupMethod, 1, beanManager, type, qualifiers); argumentLookupMethod = argumentLookupMethod.asType(argumentLookupMethod.type().changeReturnType(parameterType)); @@ -309,14 +312,20 @@ private boolean requiresCleanup() { } // replace `null` values in the arguments array with zero values - // on positions where the method accepts a primitive type - Class[] parameterTypes = method.getParameterTypes(); - if (PrimitiveUtils.hasPrimitive(parameterTypes)) { - MethodHandle replacePrimitiveNulls = MethodHandleUtils.REPLACE_PRIMITIVE_NULLS; - replacePrimitiveNulls = MethodHandles.insertArguments(replacePrimitiveNulls, 1, (Object) parameterTypes); - mh = MethodHandles.filterArguments(mh, requiresCleanup ? 2 : 1, replacePrimitiveNulls); + // on positions where the method has an argument lookup configured + // (this is just to prevent a NPE in method handles internals) + Class[] parameterTypes = reflectionMethod.getParameterTypes(); + if (LookupUtils.hasPrimitiveArgLookup(parameterTypes, argLookup)) { + MethodHandle replaceNulls = MethodHandleUtils.REPLACE_PRIMITIVE_LOOKUP_NULLS; + replaceNulls = MethodHandles.insertArguments(replaceNulls, 1, parameterTypes, argLookup); + mh = MethodHandles.filterArguments(mh, requiresCleanup ? 2 : 1, replaceNulls); } + // trim argument array if needed + MethodHandle trimArgumentArray = MethodHandles.insertArguments(MethodHandleUtils.TRIM_ARRAY_TO_SIZE, + 1, reflectionMethod.getParameterCount()); + mh = MethodHandles.filterArguments(mh, requiresCleanup ? 2 : 1, trimArgumentArray); + // instantiate `CleanupActions` if (requiresCleanup) { mh = MethodHandles.foldArguments(mh, MethodHandleUtils.CLEANUP_ACTIONS_CTOR); @@ -326,12 +335,37 @@ private boolean requiresCleanup() { if (invocationWrapper != null) { InvokerImpl invoker = new InvokerImpl<>(mh); - MethodHandle invocationWrapperMethod = MethodHandleUtils.createMethodHandleFromTransformer(method, - invocationWrapper, beanClass); + MethodHandle invocationWrapperMethod = MethodHandleUtils.createMethodHandleFromTransformer(reflectionMethod, + invocationWrapper, reflectionBeanClass); mh = MethodHandles.insertArguments(invocationWrapperMethod, 2, invoker); } return new InvokerImpl<>(mh); } + + // the following methods are exposed for deployment validation + + public AnnotatedType getBeanClass() { + return beanClass; + } + + public TargetMethod getMethod() { + return method; + } + + public List getConfiguredLookups() { + List result = new ArrayList<>(); + if (instanceLookup) { + result.add(new ConfiguredLookup(-1, beanClass.getJavaClass(), + LookupUtils.extractQualifiers(beanClass.getAnnotations(), beanManager))); + } + for (int i = 0; i < argLookup.length; i++) { + if (argLookup[i]) { + result.add(new ConfiguredLookup(i, method.getParameterType(i), + LookupUtils.extractQualifiers(method.getParameterAnnotations(i), beanManager))); + } + } + return result; + } } diff --git a/impl/src/main/java/org/jboss/weld/invokable/ArrayUtils.java b/impl/src/main/java/org/jboss/weld/invokable/ArrayUtils.java new file mode 100644 index 0000000000..8526ced11f --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/invokable/ArrayUtils.java @@ -0,0 +1,15 @@ +package org.jboss.weld.invokable; + +class ArrayUtils { + private ArrayUtils() { + } + + static Object[] trimArrayToSize(Object[] array, int size) { + if (array == null || array.length <= size) { + return array; + } + Object[] result = new Object[size]; + System.arraycopy(array, 0, result, 0, size); + return result; + } +} diff --git a/impl/src/main/java/org/jboss/weld/invokable/ConfiguredLookup.java b/impl/src/main/java/org/jboss/weld/invokable/ConfiguredLookup.java new file mode 100644 index 0000000000..bf88115d01 --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/invokable/ConfiguredLookup.java @@ -0,0 +1,20 @@ +package org.jboss.weld.invokable; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +public final class ConfiguredLookup { + public final int position; // -1 for instance lookup, >= 0 for argument lookups + public final Type type; + public final Annotation[] qualifiers; + + ConfiguredLookup(int position, Type type, Annotation[] qualifiers) { + this.position = position; + this.type = type; + this.qualifiers = qualifiers; + } + + public boolean isInstanceLookup() { + return position < 0; + } +} diff --git a/impl/src/main/java/org/jboss/weld/invokable/InvokerBuilderImpl.java b/impl/src/main/java/org/jboss/weld/invokable/InvokerBuilderImpl.java index 7503a15cb5..26847f24f4 100644 --- a/impl/src/main/java/org/jboss/weld/invokable/InvokerBuilderImpl.java +++ b/impl/src/main/java/org/jboss/weld/invokable/InvokerBuilderImpl.java @@ -1,13 +1,13 @@ package org.jboss.weld.invokable; -import java.lang.reflect.Method; - -import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.enterprise.inject.spi.AnnotatedType; import jakarta.enterprise.invoke.Invoker; +import org.jboss.weld.manager.BeanManagerImpl; + public class InvokerBuilderImpl extends AbstractInvokerBuilder> { - public InvokerBuilderImpl(Class beanClass, Method method, BeanManager beanManager) { + public InvokerBuilderImpl(AnnotatedType beanClass, TargetMethod method, BeanManagerImpl beanManager) { super(beanClass, method, beanManager); } diff --git a/impl/src/main/java/org/jboss/weld/invokable/InvokerImpl.java b/impl/src/main/java/org/jboss/weld/invokable/InvokerImpl.java index cd6a300e1e..792f5b4a67 100644 --- a/impl/src/main/java/org/jboss/weld/invokable/InvokerImpl.java +++ b/impl/src/main/java/org/jboss/weld/invokable/InvokerImpl.java @@ -13,7 +13,7 @@ public class InvokerImpl implements Invoker, InvokerInfo { } @Override - public R invoke(T instance, Object[] arguments) { + public R invoke(T instance, Object[] arguments) throws Exception { try { return (R) mh.invoke(instance, arguments); } catch (ValueCarryingException e) { diff --git a/impl/src/main/java/org/jboss/weld/invokable/InvokerInfoBuilder.java b/impl/src/main/java/org/jboss/weld/invokable/InvokerInfoBuilder.java index 613816c645..d506e88a92 100644 --- a/impl/src/main/java/org/jboss/weld/invokable/InvokerInfoBuilder.java +++ b/impl/src/main/java/org/jboss/weld/invokable/InvokerInfoBuilder.java @@ -1,14 +1,16 @@ package org.jboss.weld.invokable; -import java.lang.reflect.Method; - import jakarta.enterprise.inject.build.compatible.spi.InvokerInfo; +import jakarta.enterprise.inject.spi.AnnotatedType; import jakarta.enterprise.inject.spi.BeanManager; +import org.jboss.weld.manager.BeanManagerImpl; +import org.jboss.weld.manager.api.WeldManager; + public class InvokerInfoBuilder extends AbstractInvokerBuilder { - public InvokerInfoBuilder(Class beanClass, Method method, BeanManager beanManager) { - super(beanClass, method, beanManager); + public InvokerInfoBuilder(AnnotatedType beanClass, TargetMethod method, BeanManager beanManager) { + super(beanClass, method, (BeanManagerImpl) ((WeldManager) beanManager).unwrap()); } @Override diff --git a/impl/src/main/java/org/jboss/weld/invokable/LookupUtils.java b/impl/src/main/java/org/jboss/weld/invokable/LookupUtils.java index c6ccc46c2a..d65cd56489 100644 --- a/impl/src/main/java/org/jboss/weld/invokable/LookupUtils.java +++ b/impl/src/main/java/org/jboss/weld/invokable/LookupUtils.java @@ -1,10 +1,11 @@ package org.jboss.weld.invokable; import java.lang.annotation.Annotation; -import java.lang.reflect.Parameter; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Map; import jakarta.enterprise.inject.Default; import jakarta.enterprise.inject.Instance; @@ -17,6 +18,35 @@ class LookupUtils { private LookupUtils() { } + private static final Map, Object> PRIMITIVE_WRAPPER_ZERO_VALUES = Map.ofEntries( + Map.entry(boolean.class, false), + Map.entry(byte.class, (byte) 0), + Map.entry(short.class, (short) 0), + Map.entry(int.class, 0), + Map.entry(long.class, 0L), + Map.entry(float.class, 0.0F), + Map.entry(double.class, 0.0), + Map.entry(char.class, (char) 0)); + + static boolean hasPrimitiveArgLookup(Class[] types, boolean[] argLookup) { + for (int i = 0; i < Math.min(types.length, argLookup.length); i++) { + if (types[i].isPrimitive() && argLookup[i]) { + return true; + } + } + return false; + } + + static Object[] replacePrimitiveLookupNulls(Object[] values, Class[] types, boolean[] argLookup) { + for (int i = 0; i < values.length; i++) { + Class type = types[i]; + if (values[i] == null && type.isPrimitive() && argLookup[i]) { + values[i] = PRIMITIVE_WRAPPER_ZERO_VALUES.get(type); + } + } + return values; + } + static Object lookup(CleanupActions cleanup, BeanManager beanManager, Type type, Annotation[] qualifiers) { WeldInstance lookup = (WeldInstance) beanManager.createInstance(); Instance.Handle result = lookup.select(type, qualifiers).getHandle(); @@ -24,15 +54,7 @@ static Object lookup(CleanupActions cleanup, BeanManager beanManager, Type type, return result.get(); } - static Annotation[] classQualifiers(Class beanClass, BeanManager bm) { - return findQualifiers(beanClass.getAnnotations(), bm); - } - - static Annotation[] parameterQualifiers(Parameter parameter, BeanManager bm) { - return findQualifiers(parameter.getAnnotations(), bm); - } - - private static Annotation[] findQualifiers(Annotation[] annotations, BeanManager bm) { + static Annotation[] extractQualifiers(Collection annotations, BeanManager bm) { List qualifiers = new ArrayList<>(); for (Annotation a : annotations) { if (bm.isQualifier(a.annotationType())) { diff --git a/impl/src/main/java/org/jboss/weld/invokable/MethodHandleUtils.java b/impl/src/main/java/org/jboss/weld/invokable/MethodHandleUtils.java index 54aac38228..588c9fe5c1 100644 --- a/impl/src/main/java/org/jboss/weld/invokable/MethodHandleUtils.java +++ b/impl/src/main/java/org/jboss/weld/invokable/MethodHandleUtils.java @@ -25,8 +25,9 @@ private MethodHandleUtils() { static final MethodHandle CLEANUP_FOR_VOID; static final MethodHandle CLEANUP_FOR_NONVOID; static final MethodHandle LOOKUP; - static final MethodHandle REPLACE_PRIMITIVE_NULLS; + static final MethodHandle REPLACE_PRIMITIVE_LOOKUP_NULLS; static final MethodHandle THROW_VALUE_CARRYING_EXCEPTION; + static final MethodHandle TRIM_ARRAY_TO_SIZE; static { try { @@ -38,10 +39,12 @@ private MethodHandleUtils() { runName, Throwable.class, Object.class, CleanupActions.class)); LOOKUP = createMethodHandle(LookupUtils.class.getDeclaredMethod( "lookup", CleanupActions.class, BeanManager.class, Type.class, Annotation[].class)); - REPLACE_PRIMITIVE_NULLS = MethodHandleUtils.createMethodHandle(PrimitiveUtils.class.getDeclaredMethod( - "replacePrimitiveNulls", Object[].class, Class[].class)); + REPLACE_PRIMITIVE_LOOKUP_NULLS = MethodHandleUtils.createMethodHandle(LookupUtils.class.getDeclaredMethod( + "replacePrimitiveLookupNulls", Object[].class, Class[].class, boolean[].class)); THROW_VALUE_CARRYING_EXCEPTION = createMethodHandle(ValueCarryingException.class.getDeclaredMethod( "throwReturnValue", Object.class)); + TRIM_ARRAY_TO_SIZE = createMethodHandle(ArrayUtils.class.getDeclaredMethod( + "trimArrayToSize", Object[].class, int.class)); } catch (NoSuchMethodException e) { // should never happen throw new IllegalStateException("Unable to locate Weld internal helper method", e); @@ -100,11 +103,11 @@ static MethodHandle createMethodHandleFromTransformer(Method targetMethod, Trans } } if (matchingMethods.isEmpty()) { - // TODO better exception + // TODO better exception, use Logger interface throw new DeploymentException(transformer + ": no method found"); } if (matchingMethods.size() > 1) { - // TODO better exception + // TODO better exception, use Logger interface throw new DeploymentException(transformer + ": more than one method found: " + matchingMethods); } Method method = matchingMethods.get(0); @@ -149,7 +152,7 @@ static MethodHandle createMethodHandleFromTransformer(Method targetMethod, Trans private static void validateTransformerMethod(Method m, TransformerMetadata transformer, Class transformationArgType) { // all transformers have to be public to ensure accessibility if (!Modifier.isPublic(m.getModifiers())) { - // TODO better exception + // TODO better exception, use Logger interface throw new DeploymentException("All invocation transformers need to be public - " + transformer); } @@ -157,28 +160,28 @@ private static void validateTransformerMethod(Method m, TransformerMetadata tran if (transformer.isInputTransformer()) { // input transformers need to validate assignability of their return type versus original arg type if (!transformationArgType.isAssignableFrom(m.getReturnType())) { - // TODO better exception + // TODO better exception, use Logger interface throw new DeploymentException("Input transformer " + transformer + " has a return value that is not assignable to expected class: " + transformationArgType); } // instance method is no-param, otherwise its 1-2 with second being Consumer if (!Modifier.isStatic(m.getModifiers())) { if (paramCount != 0) { - // TODO better exception + // TODO better exception, use Logger interface throw new DeploymentException( "Non-static input transformers are expected to have zero input parameters! Transformer: " + transformer); } } else { if (paramCount > 2) { - // TODO better exception + // TODO better exception, use Logger interface throw new DeploymentException( "Static input transformers can only have one or two parameters. " + transformer); } if (paramCount == 2) { // we do not validate type param of Consumer, i.e. if it's exactly Consumer if (!Consumer.class.equals(m.getParameters()[1].getType())) { - // TODO better exception + // TODO better exception, use Logger interface throw new DeploymentException( "Static input transformers with two parameters can only have Consumer as their second parameter! " + transformer); @@ -190,19 +193,19 @@ private static void validateTransformerMethod(Method m, TransformerMetadata tran // this also means instance methods need no validation in this regard if (!Modifier.isStatic(m.getModifiers())) { if (paramCount != 0) { - // TODO better exception + // TODO better exception, use Logger interface throw new DeploymentException( "Non-static output transformers are expected to have zero input parameters! Transformer: " + transformer); } } else { if (paramCount != 1) { - // TODO better exception + // TODO better exception, use Logger interface throw new DeploymentException( "Static output transformers are expected to have one input parameter! Transformer: " + transformer); } if (!m.getParameters()[0].getType().isAssignableFrom(transformationArgType)) { - // TODO better exception + // TODO better exception, use Logger interface throw new DeploymentException("Output transformer " + transformer + " parameter is not assignable to the expected type " + transformationArgType); } @@ -216,7 +219,7 @@ private static void validateTransformerMethod(Method m, TransformerMetadata tran && params[2].equals(Invoker.class)) { // OK } else { - // TODO better exception + // TODO better exception, use Logger interface throw new DeploymentException("Invocation wrapper has unexpected parameters " + transformer + "\nExpected param types are: " + transformationArgType + ", Object[], Invoker.class"); } diff --git a/impl/src/main/java/org/jboss/weld/invokable/PrimitiveUtils.java b/impl/src/main/java/org/jboss/weld/invokable/PrimitiveUtils.java deleted file mode 100644 index a9f900687a..0000000000 --- a/impl/src/main/java/org/jboss/weld/invokable/PrimitiveUtils.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.jboss.weld.invokable; - -import java.util.Map; - -class PrimitiveUtils { - private PrimitiveUtils() { - } - - private static final Map, Object> PRIMITIVE_WRAPPER_ZERO_VALUES = Map.ofEntries( - Map.entry(boolean.class, false), - Map.entry(byte.class, (byte) 0), - Map.entry(short.class, (short) 0), - Map.entry(int.class, 0), - Map.entry(long.class, 0L), - Map.entry(float.class, 0.0F), - Map.entry(double.class, 0.0), - Map.entry(char.class, (char) 0)); - - static boolean hasPrimitive(Class[] types) { - for (Class type : types) { - if (type.isPrimitive()) { - return true; - } - } - return false; - } - - static Object[] replacePrimitiveNulls(Object[] values, Class[] types) { - for (int i = 0; i < values.length; i++) { - Class type = types[i]; - if (values[i] == null && type.isPrimitive()) { - values[i] = PRIMITIVE_WRAPPER_ZERO_VALUES.get(type); - } - } - return values; - } -} diff --git a/impl/src/main/java/org/jboss/weld/invokable/TargetMethod.java b/impl/src/main/java/org/jboss/weld/invokable/TargetMethod.java new file mode 100644 index 0000000000..997be4340f --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/invokable/TargetMethod.java @@ -0,0 +1,48 @@ +package org.jboss.weld.invokable; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Collection; + +import jakarta.enterprise.inject.spi.AnnotatedMethod; + +public final class TargetMethod { + private final Method reflection; + private final AnnotatedMethod cdi; + + public TargetMethod(Method reflectionMethod) { + this.reflection = reflectionMethod; + this.cdi = null; + } + + public TargetMethod(AnnotatedMethod cdiMethod) { + this.reflection = cdiMethod.getJavaMember(); + this.cdi = cdiMethod; + } + + public Method getReflection() { + return reflection; + } + + public boolean isStatic() { + return Modifier.isStatic(reflection.getModifiers()); + } + + public int getParameterCount() { + return reflection.getParameterCount(); + } + + public Type getParameterType(int position) { + return reflection.getGenericParameterTypes()[position]; + } + + public Collection getParameterAnnotations(int position) { + if (cdi != null) { + return cdi.getParameters().get(position).getAnnotations(); + } + return Arrays.asList(reflection.getParameterAnnotations()[position]); + } +} diff --git a/impl/src/main/java/org/jboss/weld/logging/ValidatorLogger.java b/impl/src/main/java/org/jboss/weld/logging/ValidatorLogger.java index 5ba00fbf41..e63d5891dc 100644 --- a/impl/src/main/java/org/jboss/weld/logging/ValidatorLogger.java +++ b/impl/src/main/java/org/jboss/weld/logging/ValidatorLogger.java @@ -305,4 +305,15 @@ UnserializableDependencyException interceptorDecoratorInjectionPointHasNonSerial DefinitionException interceptorMethodDeclaresMultipleParameters(Object param1, Object param2, Object param3, Object stackElement); + @Message(id = 1486, value = "Instance lookup configured for target bean {0} and target method {1} is unsatisfied", format = Format.MESSAGE_FORMAT) + DeploymentException invokerUnsatisfiedInstanceLookup(Class beanClass, Method method); + + @Message(id = 1487, value = "Instance lookup configured for target bean {0} and target method {1} is ambiguous", format = Format.MESSAGE_FORMAT) + DeploymentException invokerAmbiguousInstanceLookup(Class beanClass, Method method); + + @Message(id = 1488, value = "Argument lookup configured for target bean {0} and parameter {2} of target method {1} is unsatisfied", format = Format.MESSAGE_FORMAT) + DeploymentException invokerUnsatisfiedArgumentLookup(Class beanClass, Method method, int position); + + @Message(id = 1489, value = "Argument lookup configured for target bean {0} and parameter {2} of target method {1} is ambiguous", format = Format.MESSAGE_FORMAT) + DeploymentException invokerAmbiguousArgumentLookup(Class beanClass, Method method, int position); } diff --git a/impl/src/main/java/org/jboss/weld/manager/BeanManagerImpl.java b/impl/src/main/java/org/jboss/weld/manager/BeanManagerImpl.java index 451285d7e6..d797bfa0f6 100644 --- a/impl/src/main/java/org/jboss/weld/manager/BeanManagerImpl.java +++ b/impl/src/main/java/org/jboss/weld/manager/BeanManagerImpl.java @@ -128,6 +128,7 @@ import org.jboss.weld.exceptions.IllegalArgumentException; import org.jboss.weld.exceptions.IllegalStateException; import org.jboss.weld.exceptions.InjectionException; +import org.jboss.weld.exceptions.UnsupportedOperationException; import org.jboss.weld.inject.WeldInstance; import org.jboss.weld.injection.CurrentInjectionPoint; import org.jboss.weld.injection.EmptyInjectionPoint; @@ -140,6 +141,7 @@ import org.jboss.weld.injection.producer.WeldInjectionTargetBuilderImpl; import org.jboss.weld.interceptor.reader.InterceptorMetadataReader; import org.jboss.weld.interceptor.spi.model.InterceptionModel; +import org.jboss.weld.invokable.AbstractInvokerBuilder; import org.jboss.weld.logging.BeanManagerLogger; import org.jboss.weld.logging.BootstrapLogger; import org.jboss.weld.manager.api.WeldInjectionTargetBuilder; @@ -255,7 +257,7 @@ public class BeanManagerImpl implements WeldManager, Serializable { /* * These data structures are scoped to this bean deployment archive only and represent the beans, decorators, interceptors, - * namespaces and observers + * namespaces, observers and invokers * deployed in this bean deployment archive */ private final transient List> enabledBeans; @@ -266,6 +268,7 @@ public class BeanManagerImpl implements WeldManager, Serializable { private final transient List> interceptors; private final transient List namespaces; private final transient List> observers; + private final transient List> invokers; // only for validation, cleaned up afterward /* * set that is only used to make sure that no duplicate beans are added @@ -321,7 +324,8 @@ public static BeanManagerImpl newRootManager(String contextId, String id, Servic return new BeanManagerImpl(serviceRegistry, new CopyOnWriteArrayList>(), new CopyOnWriteArrayList>(), new CopyOnWriteArrayList>(), new CopyOnWriteArrayList>(), new CopyOnWriteArrayList>(), - new CopyOnWriteArrayList(), new ConcurrentHashMap, SessionBean>(), + new CopyOnWriteArrayList(), new CopyOnWriteArrayList>(), + new ConcurrentHashMap, SessionBean>(), new ClientProxyProvider(contextId), contexts, ModuleEnablement.EMPTY_ENABLEMENT, id, new AtomicInteger(), new HashSet(), contextId); } @@ -330,15 +334,15 @@ public static BeanManagerImpl newManager(BeanManagerImpl rootManager, String id, return new BeanManagerImpl(services, new CopyOnWriteArrayList>(), new CopyOnWriteArrayList>(), new CopyOnWriteArrayList>(), new CopyOnWriteArrayList>(), new CopyOnWriteArrayList>(), - new CopyOnWriteArrayList(), + new CopyOnWriteArrayList(), new CopyOnWriteArrayList>(), rootManager.getEnterpriseBeans(), rootManager.getClientProxyProvider(), rootManager.getContexts(), ModuleEnablement.EMPTY_ENABLEMENT, id, new AtomicInteger(), rootManager.managers, rootManager.contextId); } private BeanManagerImpl(ServiceRegistry serviceRegistry, List> beans, List> transitiveBeans, - List> decorators, - List> interceptors, List> observers, List namespaces, + List> decorators, List> interceptors, List> observers, + List namespaces, List> invokers, Map, SessionBean> enterpriseBeans, ClientProxyProvider clientProxyProvider, Map, List> contexts, ModuleEnablement enabled, String id, AtomicInteger childIds, @@ -354,6 +358,7 @@ private BeanManagerImpl(ServiceRegistry serviceRegistry, List> beans, Li this.observers = observers; this.enabled = enabled; this.namespaces = namespaces; + this.invokers = invokers; this.id = id; this.managers = managers; this.contextId = contextId; @@ -638,6 +643,14 @@ public void addObserver(ObserverMethod observer) { observers.add(observer); } + public void addInvoker(AbstractInvokerBuilder invoker) { + invokers.add(invoker); + } + + public void forgetInvokersAfterValidation() { + invokers.clear(); + } + /** * Gets an active context of the given scope. Throws an exception if there are no active contexts found or if there are too * many matches @@ -1044,6 +1057,10 @@ public List> getObservers() { return observers; } + public List> getInvokers() { + return invokers; + } + @Override public InjectionTarget createInjectionTarget(EjbDescriptor descriptor) { if (descriptor.isMessageDriven()) { @@ -1768,4 +1785,15 @@ private WeldUnusedMetadataExtension getUnusedMetadataExtension() { } } + @Override + public boolean isMatchingBean(Set beanTypes, Set beanQualifiers, Type requiredType, + Set requiredQualifiers) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isMatchingEvent(Type eventType, Set eventQualifiers, Type observedEventType, + Set observedEventQualifiers) { + throw new UnsupportedOperationException(); + } } diff --git a/impl/src/main/java/org/jboss/weld/util/ForwardingBeanManager.java b/impl/src/main/java/org/jboss/weld/util/ForwardingBeanManager.java index 7b7991f0d5..ee6c9fe517 100644 --- a/impl/src/main/java/org/jboss/weld/util/ForwardingBeanManager.java +++ b/impl/src/main/java/org/jboss/weld/util/ForwardingBeanManager.java @@ -285,4 +285,15 @@ public Instance createInstance() { return delegate().createInstance(); } + @Override + public boolean isMatchingBean(Set beanTypes, Set beanQualifiers, Type requiredType, + Set requiredQualifiers) { + return delegate().isMatchingBean(beanTypes, beanQualifiers, requiredType, requiredQualifiers); + } + + @Override + public boolean isMatchingEvent(Type eventType, Set eventQualifiers, Type observedEventType, + Set observedEventQualifiers) { + return delegate().isMatchingEvent(eventType, eventQualifiers, observedEventType, observedEventQualifiers); + } } diff --git a/impl/src/test/java/org/jboss/weld/invokable/Playground_Spread.java b/impl/src/test/java/org/jboss/weld/invokable/Playground_Spread.java index 7b0073e54b..b440127537 100644 --- a/impl/src/test/java/org/jboss/weld/invokable/Playground_Spread.java +++ b/impl/src/test/java/org/jboss/weld/invokable/Playground_Spread.java @@ -31,16 +31,15 @@ public static void main(String[] args) throws Throwable { } System.out.println("!!!!!!! 3 " + mh.type()); - Class[] parameterTypes = targetMethod.getParameterTypes(); - if (PrimitiveUtils.hasPrimitive(parameterTypes)) { - MethodHandle replacePrimitiveNulls = MethodHandleUtils.createMethodHandle(PrimitiveUtils.class.getDeclaredMethod( - "replacePrimitiveNulls", Object[].class, Class[].class)); - replacePrimitiveNulls = MethodHandles.insertArguments(replacePrimitiveNulls, 1, (Object) parameterTypes); - mh = MethodHandles.filterArguments(mh, 2, replacePrimitiveNulls); - } + // trim argument array if needed + Method trimArrayToSize = ArrayUtils.class.getDeclaredMethod("trimArrayToSize", Object[].class, int.class); + MethodHandle trimmer = MethodHandleUtils.createMethodHandle(trimArrayToSize); + trimmer = MethodHandles.insertArguments(trimmer, 1, targetMethod.getParameterCount()); + mh = MethodHandles.filterArguments(mh, 2, trimmer); System.out.println("!!!!!!! 4 " + mh.type()); - System.out.println(mh.invoke(new CleanupActions(), new Playground_Spread(), new Object[] { null })); + System.out.println( + mh.invoke(new CleanupActions(), new Playground_Spread(), new Object[] { 1, 2, null, "3", new Object() })); } public String hello(int param) { diff --git a/impl/src/test/java/org/jboss/weld/invokable/Playground_Wrapper.java b/impl/src/test/java/org/jboss/weld/invokable/Playground_Wrapper.java index 9379701469..f7a791a9a7 100644 --- a/impl/src/test/java/org/jboss/weld/invokable/Playground_Wrapper.java +++ b/impl/src/test/java/org/jboss/weld/invokable/Playground_Wrapper.java @@ -21,7 +21,8 @@ public static void main(String[] args) throws Throwable { System.out.println(mh.invoke(new Playground_Wrapper(), new Object[] { 42 })); } - public static String wrap(Playground_Wrapper instance, Object[] arguments, Invoker invoker) { + public static String wrap(Playground_Wrapper instance, Object[] arguments, Invoker invoker) + throws Exception { return "wrapped_" + instance + "_" + Arrays.toString(arguments) + "___" + invoker.invoke(instance, arguments); } diff --git a/pom.xml b/pom.xml index a0c3bbccaf..08e9c2b170 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,7 @@ 1.2.0.Final 2.0.1 - 4.1.0-M1 + 4.1.0-SNAPSHOT @@ -88,8 +88,8 @@ 1.2.6 2.0.0 3.3.0 - 7.4.0 - 6.0.Alpha2 + 7.9.0 + 6.0-SNAPSHOT 1.0.3.Final 5.0.1.Final diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/BuildCompatExtension.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/BuildCompatExtension.java index 5fdb5340ad..150a2d7414 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/BuildCompatExtension.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/BuildCompatExtension.java @@ -6,6 +6,7 @@ import jakarta.enterprise.inject.Instance; import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; import jakarta.enterprise.inject.build.compatible.spi.InvokerInfo; import jakarta.enterprise.inject.build.compatible.spi.Parameters; import jakarta.enterprise.inject.build.compatible.spi.Registration; @@ -15,6 +16,7 @@ import jakarta.enterprise.invoke.Invoker; import jakarta.enterprise.lang.model.declarations.MethodInfo; +import org.jboss.weld.invoke.WeldInvokerBuilder; import org.jboss.weld.tests.invokable.common.ArgTransformer; import org.jboss.weld.tests.invokable.common.ExceptionTransformer; import org.jboss.weld.tests.invokable.common.FooArg; @@ -132,127 +134,135 @@ public void synth(SyntheticComponents syntheticComponents) { } @Registration(types = SimpleBean.class) - public void createNoTransformationInvokers(BeanInfo b) { + public void createNoTransformationInvokers(BeanInfo b, InvokerFactory invokers) { Collection invokableMethods = b.declaringClass().methods(); Assert.assertEquals(4, invokableMethods.size()); for (MethodInfo invokableMethod : invokableMethods) { if (invokableMethod.name().contains("staticPing")) { - staticNoTransformationInvoker = b.createInvoker(invokableMethod).build(); - staticInstanceLookupInvoker = b.createInvoker(invokableMethod).setInstanceLookup().build(); - staticArgLookupInvoker = b.createInvoker(invokableMethod).setArgumentLookup(0).setArgumentLookup(1).build(); - staticLookupAllInvoker = b.createInvoker(invokableMethod).setArgumentLookup(0).setArgumentLookup(1) - .setInstanceLookup().build(); + staticNoTransformationInvoker = invokers.createInvoker(b, invokableMethod).build(); + staticInstanceLookupInvoker = invokers.createInvoker(b, invokableMethod).withInstanceLookup().build(); + staticArgLookupInvoker = invokers.createInvoker(b, invokableMethod).withArgumentLookup(0).withArgumentLookup(1) + .build(); + staticLookupAllInvoker = invokers.createInvoker(b, invokableMethod).withArgumentLookup(0).withArgumentLookup(1) + .withInstanceLookup().build(); } else if (invokableMethod.name().contains("ping")) { - noTransformationInvoker = b.createInvoker(invokableMethod).build(); - instanceLookupInvoker = b.createInvoker(invokableMethod).setInstanceLookup().build(); - argLookupInvoker = b.createInvoker(invokableMethod).setArgumentLookup(0).setArgumentLookup(1).build(); - lookupAllInvoker = b.createInvoker(invokableMethod).setArgumentLookup(0).setArgumentLookup(1) - .setInstanceLookup().build(); + noTransformationInvoker = invokers.createInvoker(b, invokableMethod).build(); + instanceLookupInvoker = invokers.createInvoker(b, invokableMethod).withInstanceLookup().build(); + argLookupInvoker = invokers.createInvoker(b, invokableMethod).withArgumentLookup(0).withArgumentLookup(1) + .build(); + lookupAllInvoker = invokers.createInvoker(b, invokableMethod).withArgumentLookup(0).withArgumentLookup(1) + .withInstanceLookup().build(); } } } @Registration(types = TransformableBean.class) - public void createArgTransformationInvokers(BeanInfo b) { + public void createArgTransformationInvokers(BeanInfo b, InvokerFactory invokers) { Collection invokableMethods = b.declaringClass().methods(); Assert.assertEquals(4, invokableMethods.size()); for (MethodInfo invokableMethod : invokableMethods) { if (invokableMethod.name().contains("staticPing")) { - staticArgTransformingInvoker = b.createInvoker(invokableMethod) - .setArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static transformer method - .setArgumentTransformer(1, ArgTransformer.class, "transform") // static transformer method + staticArgTransformingInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, invokableMethod)) + .withArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static Transformer method + .withArgumentTransformer(1, ArgTransformer.class, "transform") // static Transformer method .build(); - staticArgTransformerWithConsumerInvoker = b.createInvoker(invokableMethod) - .setArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static transformer method - .setArgumentTransformer(1, ArgTransformer.class, "transform2") // static transformer method with Consumer + staticArgTransformerWithConsumerInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, + invokableMethod)) + .withArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static Transformer method + .withArgumentTransformer(1, ArgTransformer.class, "transform2") // static Transformer method with Consumer .build(); } else if (invokableMethod.name().contains("ping")) { - argTransformingInvoker = b.createInvoker(invokableMethod) - .setArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static transformer method - .setArgumentTransformer(1, ArgTransformer.class, "transform") // static transformer method + argTransformingInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, invokableMethod)) + .withArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static Transformer method + .withArgumentTransformer(1, ArgTransformer.class, "transform") // static Transformer method .build(); - argTransformerWithConsumerInvoker = b.createInvoker(invokableMethod) - .setArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static transformer method - .setArgumentTransformer(1, ArgTransformer.class, "transform2") // static transformer method with Consumer + argTransformerWithConsumerInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, + invokableMethod)) + .withArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static Transformer method + .withArgumentTransformer(1, ArgTransformer.class, "transform2") // static Transformer method with Consumer .build(); } } } @Registration(types = TransformableBean.class) - public void createInstanceTransformationInvokers(BeanInfo b) { + public void createInstanceTransformationInvokers(BeanInfo b, InvokerFactory invokers) { Collection invokableMethods = b.declaringClass().methods(); Assert.assertEquals(4, invokableMethods.size()); for (MethodInfo invokableMethod : invokableMethods) { if (invokableMethod.name().contains("ping")) { - instanceTransformerInvoker = b.createInvoker(invokableMethod) - .setInstanceTransformer(InstanceTransformer.class, "transform") + instanceTransformerInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, invokableMethod)) + .withInstanceTransformer(InstanceTransformer.class, "transform") .build(); - instanceTransformerWithConsumerInvoker = b.createInvoker(invokableMethod) - .setInstanceTransformer(InstanceTransformer.class, "transform2") + instanceTransformerWithConsumerInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, + invokableMethod)) + .withInstanceTransformer(InstanceTransformer.class, "transform2") .build(); - instanceTransformerNoParamInvoker = b.createInvoker(invokableMethod) - .setInstanceTransformer(TransformableBean.class, "setTransformed") + instanceTransformerNoParamInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, + invokableMethod)) + .withInstanceTransformer(TransformableBean.class, "setTransformed") .build(); } } } @Registration(types = TransformableBean.class) - public void createReturnValueTransformationInvokers(BeanInfo b) { + public void createReturnValueTransformationInvokers(BeanInfo b, InvokerFactory invokers) { Collection invokableMethods = b.declaringClass().methods(); Assert.assertEquals(4, invokableMethods.size()); for (MethodInfo invokableMethod : invokableMethods) { if (invokableMethod.name().contains("ping")) { - returnTransformerInvoker = b.createInvoker(invokableMethod) - .setReturnValueTransformer(ReturnValueTransformer.class, "transform") + returnTransformerInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, invokableMethod)) + .withReturnValueTransformer(ReturnValueTransformer.class, "transform") .build(); - returnTransformerNoParamInvoker = b.createInvoker(invokableMethod) - .setReturnValueTransformer(String.class, "strip") + returnTransformerNoParamInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, invokableMethod)) + .withReturnValueTransformer(String.class, "strip") .build(); } else if (invokableMethod.name().contains("staticPing")) { - staticReturnTransformerInvoker = b.createInvoker(invokableMethod) - .setReturnValueTransformer(ReturnValueTransformer.class, "transform") + staticReturnTransformerInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, invokableMethod)) + .withReturnValueTransformer(ReturnValueTransformer.class, "transform") .build(); - staticReturnTransformerNoParamInvoker = b.createInvoker(invokableMethod) - .setReturnValueTransformer(String.class, "strip") + staticReturnTransformerNoParamInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, + invokableMethod)) + .withReturnValueTransformer(String.class, "strip") .build(); } } } @Registration(types = TrulyExceptionalBean.class) - public void createExceptionTransformationInvokers(BeanInfo b) { + public void createExceptionTransformationInvokers(BeanInfo b, InvokerFactory invokers) { Collection invokableMethods = b.declaringClass().methods(); Assert.assertEquals(2, invokableMethods.size()); for (MethodInfo invokableMethod : invokableMethods) { if (invokableMethod.name().contains("ping")) { - exceptionTransformerInvoker = b.createInvoker(invokableMethod) - .setExceptionTransformer(ExceptionTransformer.class, "transform") + exceptionTransformerInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, invokableMethod)) + .withExceptionTransformer(ExceptionTransformer.class, "transform") .build(); } else if (invokableMethod.name().contains("staticPing")) { - staticExceptionTransformerInvoker = b.createInvoker(invokableMethod) - .setExceptionTransformer(ExceptionTransformer.class, "transform") + staticExceptionTransformerInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, + invokableMethod)) + .withExceptionTransformer(ExceptionTransformer.class, "transform") .build(); } } } @Registration(types = SimpleBean.class) - public void createInvocationWrapperInvokers(BeanInfo b) { + public void createInvocationWrapperInvokers(BeanInfo b, InvokerFactory invokers) { Collection invokableMethods = b.declaringClass().methods(); Assert.assertEquals(4, invokableMethods.size()); for (MethodInfo invokableMethod : invokableMethods) { if (invokableMethod.name().contains("ping")) { - invocationWrapperInvoker = b.createInvoker(invokableMethod) - .setInvocationWrapper(InvocationWrapper.class, "transform") + invocationWrapperInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, invokableMethod)) + .withInvocationWrapper(InvocationWrapper.class, "transform") .build(); } else if (invokableMethod.name().contains("staticPing")) { - staticInvocationWrapperInvoker = b.createInvoker(invokableMethod) - .setInvocationWrapper(InvocationWrapper.class, "transform") + staticInvocationWrapperInvoker = ((WeldInvokerBuilder) invokers.createInvoker(b, invokableMethod)) + .withInvocationWrapper(InvocationWrapper.class, "transform") .build(); } } diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/InvokableMethodBCETest.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/InvokableMethodBCETest.java index 0647a3cb8f..2a484b3a94 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/InvokableMethodBCETest.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/InvokableMethodBCETest.java @@ -44,7 +44,7 @@ public static Archive getDeployment() { SynthBean synthBean; @Test - public void testSimpleInvokableMethod() { + public void testSimpleInvokableMethod() throws Exception { SimpleBean.resetDestroyCounter(); HelperBean.clearDestroyedCounters(); @@ -74,7 +74,7 @@ public void testSimpleInvokableMethod() { } @Test - public void testSimpleStaticInvokableMethod() { + public void testSimpleStaticInvokableMethod() throws Exception { SimpleBean.resetDestroyCounter(); HelperBean.clearDestroyedCounters(); @@ -105,7 +105,7 @@ public void testSimpleStaticInvokableMethod() { } @Test - public void testArgTransformingInvokableMethod() { + public void testArgTransformingInvokableMethod() throws Exception { ArgTransformer.runnableExecuted = 0; String fooArg = "fooArg"; @@ -126,7 +126,7 @@ public void testArgTransformingInvokableMethod() { } @Test - public void testInstanceTransformingInvokableMethod() { + public void testInstanceTransformingInvokableMethod() throws Exception { InstanceTransformer.runnableExecuted = 0; //test is intentionally *NOT* using the bean, but instead passes in new instance every time @@ -159,7 +159,7 @@ public void testInstanceTransformingInvokableMethod() { } @Test - public void testReturnValueTransformingInvokableMethod() { + public void testReturnValueTransformingInvokableMethod() throws Exception { String fooArg = " fooArg "; String expected = (fooArg + fooArg).strip(); @@ -177,7 +177,7 @@ public void testReturnValueTransformingInvokableMethod() { } @Test - public void testExceptionTransformingInvokableMethod() { + public void testExceptionTransformingInvokableMethod() throws Exception { String expected = IllegalArgumentException.class.getSimpleName(); String expectedStatic = IllegalStateException.class.getSimpleName(); @@ -189,7 +189,7 @@ public void testExceptionTransformingInvokableMethod() { } @Test - public void testInvocationWrapperInvokableMethod() { + public void testInvocationWrapperInvokableMethod() throws Exception { String expected = "foo42foo42"; // invocation wrapper defined on other class diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/InvokableMethodTest.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/InvokableMethodTest.java index b82c9efde9..1c327af071 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/InvokableMethodTest.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/InvokableMethodTest.java @@ -44,7 +44,7 @@ public static Archive getDeployment() { TrulyExceptionalBean trulyExceptionalBean; @Test - public void testSimpleInvokableMethod() { + public void testSimpleInvokableMethod() throws Exception { SimpleBean.resetDestroyCounter(); HelperBean.clearDestroyedCounters(); @@ -74,7 +74,7 @@ public void testSimpleInvokableMethod() { } @Test - public void testSimpleStaticInvokableMethod() { + public void testSimpleStaticInvokableMethod() throws Exception { SimpleBean.resetDestroyCounter(); HelperBean.clearDestroyedCounters(); @@ -105,7 +105,7 @@ public void testSimpleStaticInvokableMethod() { } @Test - public void testArgTransformingInvokableMethod() { + public void testArgTransformingInvokableMethod() throws Exception { ArgTransformer.runnableExecuted = 0; String fooArg = "fooArg"; @@ -126,7 +126,7 @@ public void testArgTransformingInvokableMethod() { } @Test - public void testInstanceTransformingInvokableMethod() { + public void testInstanceTransformingInvokableMethod() throws Exception { InstanceTransformer.runnableExecuted = 0; //test is intentionally *NOT* using the bean, but instead passes in new instance every time @@ -159,7 +159,7 @@ public void testInstanceTransformingInvokableMethod() { } @Test - public void testReturnValueTransformingInvokableMethod() { + public void testReturnValueTransformingInvokableMethod() throws Exception { String fooArg = " fooArg "; String expected = (fooArg + fooArg).strip(); @@ -177,7 +177,7 @@ public void testReturnValueTransformingInvokableMethod() { } @Test - public void testExceptionTransformingInvokableMethod() { + public void testExceptionTransformingInvokableMethod() throws Exception { String expected = IllegalArgumentException.class.getSimpleName(); String expectedStatic = IllegalStateException.class.getSimpleName(); @@ -189,7 +189,7 @@ public void testExceptionTransformingInvokableMethod() { } @Test - public void testInvocationWrapperInvokableMethod() { + public void testInvocationWrapperInvokableMethod() throws Exception { String expected = "foo42foo42"; // invocation wrapper defined on other class diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/ObservingExtension.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/ObservingExtension.java index 7922574ac2..b1c8b1ae1c 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/ObservingExtension.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/ObservingExtension.java @@ -8,6 +8,7 @@ import jakarta.enterprise.inject.spi.ProcessManagedBean; import jakarta.enterprise.invoke.Invoker; +import org.jboss.weld.invoke.WeldInvokerBuilder; import org.jboss.weld.tests.invokable.common.ArgTransformer; import org.jboss.weld.tests.invokable.common.ExceptionTransformer; import org.jboss.weld.tests.invokable.common.FooArg; @@ -154,16 +155,16 @@ public void createNoTransformationInvokers(@Observes ProcessManagedBean invokableMethod : invokableMethods) { if (invokableMethod.getJavaMember().getName().contains("staticPing")) { staticNoTransformationInvoker = pmb.createInvoker(invokableMethod).build(); - staticInstanceLookupInvoker = pmb.createInvoker(invokableMethod).setInstanceLookup().build(); - staticArgLookupInvoker = pmb.createInvoker(invokableMethod).setArgumentLookup(0).setArgumentLookup(1).build(); - staticLookupAllInvoker = pmb.createInvoker(invokableMethod).setArgumentLookup(0).setArgumentLookup(1) - .setInstanceLookup().build(); + staticInstanceLookupInvoker = pmb.createInvoker(invokableMethod).withInstanceLookup().build(); + staticArgLookupInvoker = pmb.createInvoker(invokableMethod).withArgumentLookup(0).withArgumentLookup(1).build(); + staticLookupAllInvoker = pmb.createInvoker(invokableMethod).withArgumentLookup(0).withArgumentLookup(1) + .withInstanceLookup().build(); } else if (invokableMethod.getJavaMember().getName().contains("ping")) { noTransformationInvoker = pmb.createInvoker(invokableMethod).build(); - instanceLookupInvoker = pmb.createInvoker(invokableMethod).setInstanceLookup().build(); - argLookupInvoker = pmb.createInvoker(invokableMethod).setArgumentLookup(0).setArgumentLookup(1).build(); - lookupAllInvoker = pmb.createInvoker(invokableMethod).setArgumentLookup(0).setArgumentLookup(1) - .setInstanceLookup().build(); + instanceLookupInvoker = pmb.createInvoker(invokableMethod).withInstanceLookup().build(); + argLookupInvoker = pmb.createInvoker(invokableMethod).withArgumentLookup(0).withArgumentLookup(1).build(); + lookupAllInvoker = pmb.createInvoker(invokableMethod).withArgumentLookup(0).withArgumentLookup(1) + .withInstanceLookup().build(); } } } @@ -173,22 +174,26 @@ public void createArgTransformationInvokers(@Observes ProcessManagedBean invokableMethod : invokableMethods) { if (invokableMethod.getJavaMember().getName().contains("staticPing")) { - staticArgTransformingInvoker = pmb.createInvoker(invokableMethod) - .setArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static transformer method - .setArgumentTransformer(1, ArgTransformer.class, "transform") // static transformer method + staticArgTransformingInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static Transformer method + .withArgumentTransformer(1, ArgTransformer.class, "transform") // static Transformer method .build(); - staticArgTransformerWithConsumerInvoker = pmb.createInvoker(invokableMethod) - .setArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static transformer method - .setArgumentTransformer(1, ArgTransformer.class, "transform2") // static transformer method with Consumer + staticArgTransformerWithConsumerInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static Transformer method + .withArgumentTransformer(1, ArgTransformer.class, "transform2") // static Transformer method with Consumer .build(); } else if (invokableMethod.getJavaMember().getName().contains("ping")) { - argTransformingInvoker = pmb.createInvoker(invokableMethod) - .setArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static transformer method - .setArgumentTransformer(1, ArgTransformer.class, "transform") // static transformer method + argTransformingInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static Transformer method + .withArgumentTransformer(1, ArgTransformer.class, "transform") // static Transformer method .build(); - argTransformerWithConsumerInvoker = pmb.createInvoker(invokableMethod) - .setArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static transformer method - .setArgumentTransformer(1, ArgTransformer.class, "transform2") // static transformer method with Consumer + argTransformerWithConsumerInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withArgumentTransformer(0, FooArg.class, "doubleTheString") // non-static Transformer method + .withArgumentTransformer(1, ArgTransformer.class, "transform2") // static Transformer method with Consumer .build(); } } @@ -199,14 +204,17 @@ public void createInstanceTransformationInvokers(@Observes ProcessManagedBean invokableMethod : invokableMethods) { if (invokableMethod.getJavaMember().getName().contains("ping")) { - instanceTransformerInvoker = pmb.createInvoker(invokableMethod) - .setInstanceTransformer(InstanceTransformer.class, "transform") + instanceTransformerInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withInstanceTransformer(InstanceTransformer.class, "transform") .build(); - instanceTransformerWithConsumerInvoker = pmb.createInvoker(invokableMethod) - .setInstanceTransformer(InstanceTransformer.class, "transform2") + instanceTransformerWithConsumerInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withInstanceTransformer(InstanceTransformer.class, "transform2") .build(); - instanceTransformerNoParamInvoker = pmb.createInvoker(invokableMethod) - .setInstanceTransformer(TransformableBean.class, "setTransformed") + instanceTransformerNoParamInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withInstanceTransformer(TransformableBean.class, "setTransformed") .build(); } } @@ -217,19 +225,23 @@ public void createReturnValueTransformationInvokers(@Observes ProcessManagedBean Assert.assertEquals(4, invokableMethods.size()); for (AnnotatedMethod invokableMethod : invokableMethods) { if (invokableMethod.getJavaMember().getName().contains("ping")) { - returnTransformerInvoker = pmb.createInvoker(invokableMethod) - .setReturnValueTransformer(ReturnValueTransformer.class, "transform") + returnTransformerInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withReturnValueTransformer(ReturnValueTransformer.class, "transform") .build(); - returnTransformerNoParamInvoker = pmb.createInvoker(invokableMethod) - .setReturnValueTransformer(String.class, "strip") + returnTransformerNoParamInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withReturnValueTransformer(String.class, "strip") .build(); } else if (invokableMethod.getJavaMember().getName().contains("staticPing")) { - staticReturnTransformerInvoker = pmb.createInvoker(invokableMethod) - .setReturnValueTransformer(ReturnValueTransformer.class, "transform") + staticReturnTransformerInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withReturnValueTransformer(ReturnValueTransformer.class, "transform") .build(); - staticReturnTransformerNoParamInvoker = pmb.createInvoker(invokableMethod) - .setReturnValueTransformer(String.class, "strip") + staticReturnTransformerNoParamInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withReturnValueTransformer(String.class, "strip") .build(); } } @@ -240,13 +252,15 @@ public void createExceptionTransformationInvokers(@Observes ProcessManagedBean invokableMethod : invokableMethods) { if (invokableMethod.getJavaMember().getName().contains("ping")) { - exceptionTransformerInvoker = pmb.createInvoker(invokableMethod) - .setExceptionTransformer(ExceptionTransformer.class, "transform") + exceptionTransformerInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withExceptionTransformer(ExceptionTransformer.class, "transform") .build(); } else if (invokableMethod.getJavaMember().getName().contains("staticPing")) { - staticExceptionTransformerInvoker = pmb.createInvoker(invokableMethod) - .setExceptionTransformer(ExceptionTransformer.class, "transform") + staticExceptionTransformerInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withExceptionTransformer(ExceptionTransformer.class, "transform") .build(); } } @@ -257,13 +271,14 @@ public void createInvocationWrapperInvokers(@Observes ProcessManagedBean invokableMethod : invokableMethods) { if (invokableMethod.getJavaMember().getName().contains("ping")) { - invocationWrapperInvoker = pmb.createInvoker(invokableMethod) - .setInvocationWrapper(InvocationWrapper.class, "transform") + invocationWrapperInvoker = ((WeldInvokerBuilder>) pmb.createInvoker(invokableMethod)) + .withInvocationWrapper(InvocationWrapper.class, "transform") .build(); } else if (invokableMethod.getJavaMember().getName().contains("staticPing")) { - staticInvocationWrapperInvoker = pmb.createInvoker(invokableMethod) - .setInvocationWrapper(InvocationWrapper.class, "transform") + staticInvocationWrapperInvoker = ((WeldInvokerBuilder>) pmb + .createInvoker(invokableMethod)) + .withInvocationWrapper(InvocationWrapper.class, "transform") .build(); } } diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/common/InvocationWrapper.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/common/InvocationWrapper.java index 0d55703200..104325e45c 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/common/InvocationWrapper.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/common/InvocationWrapper.java @@ -3,7 +3,8 @@ import jakarta.enterprise.invoke.Invoker; public class InvocationWrapper { - public static Object transform(SimpleBean instance, Object[] arguments, Invoker invoker) { + public static Object transform(SimpleBean instance, Object[] arguments, Invoker invoker) + throws Exception { // perform repeated invocation; just to verify the invoker is stateless Object result1 = invoker.invoke(instance, arguments); Object result2 = invoker.invoke(instance, arguments); diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/BeanProducer.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/BeanProducer.java index 19ad91895c..37a373ee49 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/BeanProducer.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/BeanProducer.java @@ -19,18 +19,6 @@ public String produce2() { return MyQualifier2.class.getSimpleName(); } - @Produces - @MyQualifier5 - public String produceAmbig1() { - throw new IllegalStateException("Ambiguous producer should never be invoked"); - } - - @Produces - @MyQualifier5 - public String produceAmbig2() { - throw new IllegalStateException("Ambiguous producer should never be invoked"); - } - @Produces public String producePlain() { throw new IllegalStateException("No qualifier producer should never be invoked"); diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableBean.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableBean.java index 54db3689d3..cddc2ca4f4 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableBean.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableBean.java @@ -10,16 +10,6 @@ public String instanceLookup() { return InvokableBean.class.getSimpleName(); } - // there are two producers providing a bean for the first argument - public String ambiguousLookup(@MyQualifier5 String a) { - return a; - } - - // there is no bean with @MyQualifier3 - public String unsatisfiedLookup(@MyQualifier3 String a) { - return a; - } - public String correctLookup(@MyQualifier1("noMatter") @MyQualifier4("binding") String a, @MyQualifier2 String b) { return a + b; } diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableMethodLookupTest.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableMethodLookupTest.java index c92885836c..6016c145ec 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableMethodLookupTest.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableMethodLookupTest.java @@ -2,10 +2,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import jakarta.enterprise.inject.AmbiguousResolutionException; -import jakarta.enterprise.inject.UnsatisfiedResolutionException; import jakarta.enterprise.inject.spi.Extension; import jakarta.inject.Inject; @@ -36,14 +33,14 @@ public static Archive getDeployment() { InvokableBean bean; @Test - public void testInstanceLookupWithQualifiers() { + public void testInstanceLookupWithQualifiers() throws Exception { Object invokerResult = extension.getInstanceLookupInvoker().invoke(null, new Object[] {}); assertTrue(invokerResult instanceof String); assertEquals(InvokableBean.class.getSimpleName(), invokerResult); } @Test - public void testCorrectArgLookupWithQualifiers() { + public void testCorrectArgLookupWithQualifiers() throws Exception { Object invokerResult = extension.getCorrectLookupInvoker().invoke(bean, new Object[] { null, null }); assertTrue(invokerResult instanceof String); assertEquals( @@ -52,29 +49,9 @@ public void testCorrectArgLookupWithQualifiers() { } @Test - public void testLookupWithRegisteredQualifier() { + public void testLookupWithRegisteredQualifier() throws Exception { Object invokerResult = extension.getLookupWithRegisteredQualifier().invoke(bean, new Object[] { null }); assertTrue(invokerResult instanceof String); assertEquals(ToBeQualifier.class.getSimpleName(), invokerResult); } - - @Test - public void testUnsatisfiedLookupWithQualifier() { - try { - Object invokerResult = extension.getUnsatisfiedLookupInvoker().invoke(bean, new Object[] { null }); - fail(); - } catch (UnsatisfiedResolutionException e) { - // expected - } - } - - @Test - public void testAmbigLookupWithQualifiers() { - try { - Object invokerResult = extension.getAmbiguousLookupInvoker().invoke(bean, new Object[] { null }); - fail(); - } catch (AmbiguousResolutionException e) { - // expected - } - } } diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokerRegistreringExtension.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokerRegistreringExtension.java index 49eb46f3b5..59c2cc8c00 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokerRegistreringExtension.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokerRegistreringExtension.java @@ -14,8 +14,6 @@ public class InvokerRegistreringExtension implements Extension { private Invoker instanceLookupInvoker; - private Invoker unsatisfiedLookupInvoker; - private Invoker ambiguousLookupInvoker; private Invoker correctLookupInvoker; private Invoker lookupWithRegisteredQualifier; @@ -23,14 +21,6 @@ public class InvokerRegistreringExtension implements Extension { return instanceLookupInvoker; } - public Invoker getUnsatisfiedLookupInvoker() { - return unsatisfiedLookupInvoker; - } - - public Invoker getAmbiguousLookupInvoker() { - return ambiguousLookupInvoker; - } - public Invoker getCorrectLookupInvoker() { return correctLookupInvoker; } @@ -41,18 +31,14 @@ public class InvokerRegistreringExtension implements Extension { public void createInvokers(@Observes ProcessManagedBean pmb) { Collection> invokableMethods = pmb.getAnnotatedBeanClass().getMethods(); - Assert.assertEquals(5, invokableMethods.size()); + Assert.assertEquals(3, invokableMethods.size()); for (AnnotatedMethod invokableMethod : invokableMethods) { if (invokableMethod.getJavaMember().getName().contains("instanceLookup")) { - instanceLookupInvoker = pmb.createInvoker(invokableMethod).setInstanceLookup().build(); - } else if (invokableMethod.getJavaMember().getName().contains("unsatisfiedLookup")) { - unsatisfiedLookupInvoker = pmb.createInvoker(invokableMethod).setArgumentLookup(0).build(); - } else if (invokableMethod.getJavaMember().getName().contains("ambiguousLookup")) { - ambiguousLookupInvoker = pmb.createInvoker(invokableMethod).setArgumentLookup(0).build(); + instanceLookupInvoker = pmb.createInvoker(invokableMethod).withInstanceLookup().build(); } else if (invokableMethod.getJavaMember().getName().contains("lookupWithRegisteredQualifier")) { - lookupWithRegisteredQualifier = pmb.createInvoker(invokableMethod).setArgumentLookup(0).build(); + lookupWithRegisteredQualifier = pmb.createInvoker(invokableMethod).withArgumentLookup(0).build(); } else { - correctLookupInvoker = pmb.createInvoker(invokableMethod).setArgumentLookup(0).setArgumentLookup(1).build(); + correctLookupInvoker = pmb.createInvoker(invokableMethod).withArgumentLookup(0).withArgumentLookup(1).build(); } } } diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/AmbiguousLookupInvokerTest.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/AmbiguousLookupInvokerTest.java new file mode 100644 index 0000000000..90fb8b0793 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/AmbiguousLookupInvokerTest.java @@ -0,0 +1,31 @@ +package org.jboss.weld.tests.invokable.lookup.ambiguous; + +import jakarta.enterprise.inject.spi.DeploymentException; +import jakarta.enterprise.inject.spi.Extension; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.BeanArchive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.weld.test.util.Utils; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(Arquillian.class) +public class AmbiguousLookupInvokerTest { + + @Deployment + @ShouldThrowException(DeploymentException.class) + public static Archive getDeployment() { + return ShrinkWrap.create(BeanArchive.class, Utils.getDeploymentNameAsHash(AmbiguousLookupInvokerTest.class)) + .addPackage(AmbiguousLookupInvokerTest.class.getPackage()) + .addAsServiceProvider(Extension.class, InvokerRegistreringExtension.class); + } + + @Test + public void testAmbigLookupWithQualifiers() throws Exception { + // should throw deployment exception + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/BeanProducer.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/BeanProducer.java new file mode 100644 index 0000000000..a97dc06f10 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/BeanProducer.java @@ -0,0 +1,20 @@ +package org.jboss.weld.tests.invokable.lookup.ambiguous; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +@ApplicationScoped +public class BeanProducer { + + @Produces + @MyQualifier5 + public String produceAmbig1() { + throw new IllegalStateException("Ambiguous producer should never be invoked"); + } + + @Produces + @MyQualifier5 + public String produceAmbig2() { + throw new IllegalStateException("Ambiguous producer should never be invoked"); + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/InvokableBean.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/InvokableBean.java new file mode 100644 index 0000000000..fe7e449de1 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/InvokableBean.java @@ -0,0 +1,12 @@ +package org.jboss.weld.tests.invokable.lookup.ambiguous; + +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class InvokableBean { + + // there are two producers providing a bean for the first argument + public String ambiguousLookup(@MyQualifier5 String a) { + return a; + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/InvokerRegistreringExtension.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/InvokerRegistreringExtension.java new file mode 100644 index 0000000000..e769f90932 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/InvokerRegistreringExtension.java @@ -0,0 +1,26 @@ +package org.jboss.weld.tests.invokable.lookup.ambiguous; + +import java.util.Collection; + +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.spi.AnnotatedMethod; +import jakarta.enterprise.inject.spi.Extension; +import jakarta.enterprise.inject.spi.ProcessManagedBean; +import jakarta.enterprise.invoke.Invoker; + +public class InvokerRegistreringExtension implements Extension { + + private Invoker ambiguousLookupInvoker; + + public Invoker getAmbiguousLookupInvoker() { + return ambiguousLookupInvoker; + } + + public void createInvokers(@Observes ProcessManagedBean pmb) { + Collection> invokableMethods = pmb.getAnnotatedBeanClass().getMethods(); + if (invokableMethods.size() != 1) { + throw new IllegalStateException("There should be exactly one method"); + } + ambiguousLookupInvoker = pmb.createInvoker(invokableMethods.iterator().next()).withArgumentLookup(0).build(); + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier5.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/MyQualifier5.java similarity index 77% rename from tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier5.java rename to tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/MyQualifier5.java index e81d0f8c18..34dd25481f 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier5.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ambiguous/MyQualifier5.java @@ -1,4 +1,4 @@ -package org.jboss.weld.tests.invokable.lookup; +package org.jboss.weld.tests.invokable.lookup.ambiguous; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/unsatisfied/InvokableBean.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/unsatisfied/InvokableBean.java new file mode 100644 index 0000000000..a6dd793524 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/unsatisfied/InvokableBean.java @@ -0,0 +1,12 @@ +package org.jboss.weld.tests.invokable.lookup.unsatisfied; + +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class InvokableBean { + + // there is no String bean + public String unsatisfiedLookup(String a) { + return a; + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/unsatisfied/InvokerRegistreringExtension.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/unsatisfied/InvokerRegistreringExtension.java new file mode 100644 index 0000000000..dccd388a36 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/unsatisfied/InvokerRegistreringExtension.java @@ -0,0 +1,26 @@ +package org.jboss.weld.tests.invokable.lookup.unsatisfied; + +import java.util.Collection; + +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.spi.AnnotatedMethod; +import jakarta.enterprise.inject.spi.Extension; +import jakarta.enterprise.inject.spi.ProcessManagedBean; +import jakarta.enterprise.invoke.Invoker; + +public class InvokerRegistreringExtension implements Extension { + + private Invoker unsatisfiedLookupInvoker; + + public Invoker getUnsatisfiedLookupInvoker() { + return unsatisfiedLookupInvoker; + } + + public void createInvokers(@Observes ProcessManagedBean pmb) { + Collection> invokableMethods = pmb.getAnnotatedBeanClass().getMethods(); + if (invokableMethods.size() != 1) { + throw new IllegalStateException("There should be exactly one method"); + } + unsatisfiedLookupInvoker = pmb.createInvoker(invokableMethods.iterator().next()).withArgumentLookup(0).build(); + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/unsatisfied/UnsatisfiedLookupInvokerTest.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/unsatisfied/UnsatisfiedLookupInvokerTest.java new file mode 100644 index 0000000000..4d8278f323 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/unsatisfied/UnsatisfiedLookupInvokerTest.java @@ -0,0 +1,31 @@ +package org.jboss.weld.tests.invokable.lookup.unsatisfied; + +import jakarta.enterprise.inject.spi.DeploymentException; +import jakarta.enterprise.inject.spi.Extension; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.BeanArchive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.weld.test.util.Utils; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(Arquillian.class) +public class UnsatisfiedLookupInvokerTest { + + @Deployment + @ShouldThrowException(DeploymentException.class) + public static Archive getDeployment() { + return ShrinkWrap.create(BeanArchive.class, Utils.getDeploymentNameAsHash(UnsatisfiedLookupInvokerTest.class)) + .addPackage(UnsatisfiedLookupInvokerTest.class.getPackage()) + .addAsServiceProvider(Extension.class, InvokerRegistreringExtension.class); + } + + @Test + public void testUnsatisfiedLookupWithQualifier() { + // test should throw a deployment exception as the arg lookup for invoker is unsatisfied + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/input/InputTransformerTest.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/input/InputTransformerTest.java index 2cd4b6fc77..b2ef441848 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/input/InputTransformerTest.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/input/InputTransformerTest.java @@ -30,7 +30,7 @@ public static Archive getDeployment() { ActualBean bean; @Test - public void testArgTransformerAssignability() { + public void testArgTransformerAssignability() throws Exception { Beta result; // test initial state without transformers result = (Beta) extension.getNoTransformer().invoke(bean, new Object[] { 0 }); @@ -47,7 +47,7 @@ public void testArgTransformerAssignability() { } @Test - public void testInstanceTransformerAssignability() { + public void testInstanceTransformerAssignability() throws Exception { Beta result; // test initial state without transformers result = (Beta) extension.getNoTransformer().invoke(bean, new Object[] { 0 }); diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/input/ObservingExtension.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/input/ObservingExtension.java index d0419c52e5..7dc9c9a29e 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/input/ObservingExtension.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/input/ObservingExtension.java @@ -8,6 +8,7 @@ import jakarta.enterprise.inject.spi.ProcessManagedBean; import jakarta.enterprise.invoke.Invoker; +import org.jboss.weld.invoke.WeldInvokerBuilder; import org.junit.Assert; public class ObservingExtension implements Extension { @@ -44,18 +45,18 @@ public void observe(@Observes ProcessManagedBean pmb) { for (AnnotatedMethod invokableMethod : invokableMethods) { if (invokableMethod.getJavaMember().getName().contains("ping")) { noTransformer = pmb.createInvoker(invokableMethod).build(); - transformInstance1 = pmb.createInvoker(invokableMethod) - .setInstanceTransformer(Transformer.class, "transformInstance1") + transformInstance1 = ((WeldInvokerBuilder>) pmb.createInvoker(invokableMethod)) + .withInstanceTransformer(Transformer.class, "transformInstance1") .build(); - transformInstance2 = pmb.createInvoker(invokableMethod) - .setInstanceTransformer(Transformer.class, "transformInstance2") + transformInstance2 = ((WeldInvokerBuilder>) pmb.createInvoker(invokableMethod)) + .withInstanceTransformer(Transformer.class, "transformInstance2") .build(); - transformArg1 = pmb.createInvoker(invokableMethod) - .setArgumentTransformer(0, Transformer.class, "transformArg1") + transformArg1 = ((WeldInvokerBuilder>) pmb.createInvoker(invokableMethod)) + .withArgumentTransformer(0, Transformer.class, "transformArg1") .build(); - transformArg2 = pmb.createInvoker(invokableMethod) - .setArgumentTransformer(0, Transformer.class, "transformArg2") + transformArg2 = ((WeldInvokerBuilder>) pmb.createInvoker(invokableMethod)) + .withArgumentTransformer(0, Transformer.class, "transformArg2") .build(); } } diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/output/ObservingExtension.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/output/ObservingExtension.java index d05eb4d1ef..6cf4562c3e 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/output/ObservingExtension.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/output/ObservingExtension.java @@ -8,6 +8,7 @@ import jakarta.enterprise.inject.spi.ProcessManagedBean; import jakarta.enterprise.invoke.Invoker; +import org.jboss.weld.invoke.WeldInvokerBuilder; import org.junit.Assert; public class ObservingExtension implements Extension { @@ -48,11 +49,11 @@ public void observe(@Observes ProcessManagedBean pmb) { Assert.assertEquals(1, invokableMethods.size()); AnnotatedMethod invokableMethod = invokableMethods.iterator().next(); noTransformer = pmb.createInvoker(invokableMethod).build(); - transformReturnType1 = pmb.createInvoker(invokableMethod) - .setReturnValueTransformer(Transformer.class, "transformReturn1") + transformReturnType1 = ((WeldInvokerBuilder>) pmb.createInvoker(invokableMethod)) + .withReturnValueTransformer(Transformer.class, "transformReturn1") .build(); - transformReturnType2 = pmb.createInvoker(invokableMethod) - .setReturnValueTransformer(Transformer.class, "transformReturn2") + transformReturnType2 = ((WeldInvokerBuilder>) pmb.createInvoker(invokableMethod)) + .withReturnValueTransformer(Transformer.class, "transformReturn2") .build(); } @@ -61,14 +62,14 @@ public void observeExceptionally(@Observes ProcessManagedBean p Assert.assertEquals(1, invokableMethods.size()); AnnotatedMethod invokableMethod = invokableMethods.iterator().next(); - transformException1 = pmb.createInvoker(invokableMethod) - .setExceptionTransformer(Transformer.class, "transformException1") + transformException1 = ((WeldInvokerBuilder>) pmb.createInvoker(invokableMethod)) + .withExceptionTransformer(Transformer.class, "transformException1") .build(); - transformException2 = pmb.createInvoker(invokableMethod) - .setExceptionTransformer(Transformer.class, "transformException2") + transformException2 = ((WeldInvokerBuilder>) pmb.createInvoker(invokableMethod)) + .withExceptionTransformer(Transformer.class, "transformException2") .build(); - transformException3 = pmb.createInvoker(invokableMethod) - .setExceptionTransformer(Transformer.class, "transformException3") + transformException3 = ((WeldInvokerBuilder>) pmb.createInvoker(invokableMethod)) + .withExceptionTransformer(Transformer.class, "transformException3") .build(); } } diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/output/OutputTransformerTest.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/output/OutputTransformerTest.java index 7eded40861..0cdca270f0 100644 --- a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/output/OutputTransformerTest.java +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/transformers/output/OutputTransformerTest.java @@ -33,7 +33,7 @@ public static Archive getDeployment() { ExceptionalBean exceptionalBean; @Test - public void testReturnTypeTransformerAssignability() { + public void testReturnTypeTransformerAssignability() throws Exception { Beta betaResult; // test initial state without transformers betaResult = (Beta) extension.getNoTransformer().invoke(bean, new Object[] { 0 }); @@ -52,7 +52,7 @@ public void testReturnTypeTransformerAssignability() { } @Test - public void testExceptionTransformerAssignability() { + public void testExceptionTransformerAssignability() throws Exception { // apply transformers, first one swallows exception and returns Beta Object result; result = extension.getTransformException1().invoke(exceptionalBean, new Object[] { 10 }); diff --git a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/BeanInfoImpl.java b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/BeanInfoImpl.java index 33155a87ca..bd40912c73 100644 --- a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/BeanInfoImpl.java +++ b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/BeanInfoImpl.java @@ -1,6 +1,5 @@ package org.jboss.weld.lite.extension.translator; -import java.lang.reflect.Modifier; import java.util.Collection; import java.util.stream.Collectors; @@ -8,22 +7,17 @@ import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; import jakarta.enterprise.inject.build.compatible.spi.DisposerInfo; import jakarta.enterprise.inject.build.compatible.spi.InjectionPointInfo; -import jakarta.enterprise.inject.build.compatible.spi.InvokerInfo; import jakarta.enterprise.inject.build.compatible.spi.ScopeInfo; import jakarta.enterprise.inject.build.compatible.spi.StereotypeInfo; import jakarta.enterprise.inject.spi.AnnotatedMethod; import jakarta.enterprise.inject.spi.BeanManager; -import jakarta.enterprise.inject.spi.Decorator; import jakarta.enterprise.inject.spi.InjectionPoint; -import jakarta.enterprise.invoke.InvokerBuilder; import jakarta.enterprise.lang.model.AnnotationInfo; import jakarta.enterprise.lang.model.declarations.ClassInfo; import jakarta.enterprise.lang.model.declarations.FieldInfo; import jakarta.enterprise.lang.model.declarations.MethodInfo; import jakarta.enterprise.lang.model.types.Type; -import org.jboss.weld.exceptions.DeploymentException; -import org.jboss.weld.invokable.InvokerInfoBuilder; import org.jboss.weld.lite.extension.translator.util.reflection.AnnotatedTypes; class BeanInfoImpl implements BeanInfo { @@ -152,45 +146,6 @@ public Collection injectionPoints() { .collect(Collectors.toList()); } - @Override - public InvokerBuilder createInvoker(MethodInfo methodInfo) { - if (!isClassBean()) { - throw new DeploymentException("Cannot build invoker for a bean which is not a managed bean: " + this); - } - if (isInterceptor()) { - throw new DeploymentException("Cannot build invoker for an interceptor: " + this); - } - if (cdiBean instanceof Decorator) { // not representable in BCE, but can theoretically happen - throw new DeploymentException("Cannot build invoker for a decorator: " + this); - } - - if (methodInfo.isConstructor()) { - throw new DeploymentException("Cannot build invoker for a constructor: " + methodInfo); - } - if (Modifier.isPrivate(methodInfo.modifiers())) { - throw new DeploymentException("Cannot build invoker for a private method: " + methodInfo); - } - if ("java.lang.Object".equals(methodInfo.declaringClass().name()) - && !"toString".equals(methodInfo.name())) { - throw new DeploymentException("Cannot build invoker for a method declared on java.lang.Object: " + methodInfo); - } - - if (methodInfo instanceof MethodInfoImpl) { - // at this point we can be sure it is a Method, not a Constructor, so we cast it - AnnotatedMethod cdiMethod = (AnnotatedMethod) ((MethodInfoImpl) methodInfo).cdiDeclaration; - - // verify that the `methodInfo` belongs to this bean - if (!ReflectionMembers.allMethods(cdiBean.getBeanClass()).contains(cdiMethod.getJavaMember())) { - throw new DeploymentException("Method does not belong to bean " + cdiBean.getBeanClass().getName() - + ": " + methodInfo); - } - - return new InvokerInfoBuilder<>(cdiBean.getBeanClass(), cdiMethod.getJavaMember(), bm); - } else { - throw new DeploymentException("Custom implementations of MethodInfo are not supported!"); - } - } - @Override public String toString() { return "@" + cdiBean.getScope().getSimpleName() + " bean [types=" + cdiBean.getTypes() diff --git a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ClassConfigImpl.java b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ClassConfigImpl.java index a8eaa4ed57..e32c31d8fe 100644 --- a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ClassConfigImpl.java +++ b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ClassConfigImpl.java @@ -60,6 +60,7 @@ public ClassConfig removeAllAnnotations() { @Override public Collection constructors() { + // TODO not exactly according to the specification, see `ClassInfoImpl.constructors()` return configurator.constructors() .stream() .map(annotatedConstructorConfigurator -> new MethodConstructorConfigImpl(annotatedConstructorConfigurator, bm)) @@ -68,6 +69,7 @@ public Collection constructors() { @Override public Collection methods() { + // TODO not exactly according to the specification, see `ClassInfoImpl.methods()` return configurator.methods() .stream() .map(annotatedMethodConfigurator -> new MethodConfigImpl(annotatedMethodConfigurator, bm)) @@ -76,6 +78,7 @@ public Collection methods() { @Override public Collection fields() { + // TODO not exactly according to the specification, see `ClassInfoImpl.fields()` return configurator.fields() .stream() .map(annotatedFieldConfigurator -> new FieldConfigImpl(annotatedFieldConfigurator, bm)) diff --git a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ExtensionInvoker.java b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ExtensionInvoker.java index 84feb53852..22074886ac 100644 --- a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ExtensionInvoker.java +++ b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ExtensionInvoker.java @@ -30,6 +30,7 @@ class ExtensionInvoker { for (Class extensionClass : extensions) { SkipIfPortableExtensionPresent skip = extensionClass.getAnnotation(SkipIfPortableExtensionPresent.class); if (skip != null) { + // TODO only if the corresponding portable extension exists! continue; } @@ -75,46 +76,6 @@ private int getExtensionMethodPriority(java.lang.reflect.Method method) { } void callExtensionMethod(java.lang.reflect.Method method, List 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 LiteExtensionTranslatorLogger.LOG.unexpectedMethodArgument(argument); - } - } - Class extensionClass = extensionClasses.get(method.getDeclaringClass().getName()); Object extensionClassInstance = extensionClassInstances.get(extensionClass); diff --git a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ExtensionMethodParameterType.java b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ExtensionMethodParameterType.java index ee43f49c57..7052f0ed93 100644 --- a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ExtensionMethodParameterType.java +++ b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ExtensionMethodParameterType.java @@ -8,6 +8,7 @@ import jakarta.enterprise.inject.build.compatible.spi.ClassConfig; import jakarta.enterprise.inject.build.compatible.spi.FieldConfig; import jakarta.enterprise.inject.build.compatible.spi.InterceptorInfo; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; import jakarta.enterprise.inject.build.compatible.spi.Messages; import jakarta.enterprise.inject.build.compatible.spi.MetaAnnotations; import jakarta.enterprise.inject.build.compatible.spi.MethodConfig; @@ -37,6 +38,8 @@ enum ExtensionMethodParameterType { INTERCEPTOR_INFO(InterceptorInfo.class, true, ExtensionPhase.REGISTRATION), OBSERVER_INFO(ObserverInfo.class, true, ExtensionPhase.REGISTRATION), + INVOKER_FACTORY(InvokerFactory.class, false, ExtensionPhase.REGISTRATION), + SYNTHETIC_COMPONENTS(SyntheticComponents.class, false, ExtensionPhase.SYNTHESIS), MESSAGES(Messages.class, false, ExtensionPhase.DISCOVERY, ExtensionPhase.ENHANCEMENT, diff --git a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ExtensionPhaseRegistration.java b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ExtensionPhaseRegistration.java index 56e7509781..919eae4d2e 100644 --- a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ExtensionPhaseRegistration.java +++ b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ExtensionPhaseRegistration.java @@ -155,7 +155,9 @@ void runExtensionMethod(java.lang.reflect.Method method) { @Override Object argumentForExtensionMethod(ExtensionMethodParameterType type, java.lang.reflect.Method method) { - if (type == ExtensionMethodParameterType.TYPES) { + if (type == ExtensionMethodParameterType.INVOKER_FACTORY) { + return new InvokerFactoryImpl(beanManager); + } else if (type == ExtensionMethodParameterType.TYPES) { return new TypesImpl(beanManager); } diff --git a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/InvokerFactoryImpl.java b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/InvokerFactoryImpl.java new file mode 100644 index 0000000000..3cb52f0ae5 --- /dev/null +++ b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/InvokerFactoryImpl.java @@ -0,0 +1,72 @@ +package org.jboss.weld.lite.extension.translator; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.InvokerInfo; +import jakarta.enterprise.inject.spi.AnnotatedMethod; +import jakarta.enterprise.inject.spi.AnnotatedType; +import jakarta.enterprise.inject.spi.Bean; +import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.enterprise.inject.spi.Decorator; +import jakarta.enterprise.inject.spi.Interceptor; +import jakarta.enterprise.invoke.InvokerBuilder; +import jakarta.enterprise.lang.model.declarations.MethodInfo; + +import org.jboss.weld.bean.ClassBean; +import org.jboss.weld.exceptions.DeploymentException; +import org.jboss.weld.invokable.InvokerInfoBuilder; +import org.jboss.weld.invokable.TargetMethod; + +class InvokerFactoryImpl implements InvokerFactory { + private final BeanManager beanManager; + + InvokerFactoryImpl(BeanManager beanManager) { + this.beanManager = beanManager; + } + + @Override + public InvokerBuilder createInvoker(BeanInfo bean, MethodInfo method) { + Bean cdiBean = ((BeanInfoImpl) bean).cdiBean; + if (!(cdiBean instanceof ClassBean)) { + throw new DeploymentException("Cannot build invoker for a bean which is not a managed bean: " + cdiBean); + } + if (cdiBean instanceof Interceptor) { + throw new DeploymentException("Cannot build invoker for an interceptor: " + cdiBean); + } + if (cdiBean instanceof Decorator) { // not representable in BCE, but can happen + throw new DeploymentException("Cannot build invoker for a decorator: " + cdiBean); + } + + if (method.isConstructor()) { + throw new DeploymentException("Cannot build invoker for a constructor: " + method); + } + if (Modifier.isPrivate(method.modifiers())) { + throw new DeploymentException("Cannot build invoker for a private method: " + method); + } + if ("java.lang.Object".equals(method.declaringClass().name()) + && !"toString".equals(method.name())) { + throw new DeploymentException("Cannot build invoker for a method declared on java.lang.Object: " + method); + } + + if (method instanceof MethodInfoImpl) { + // at this point, it is always a Method, not a Constructor + Method reflectionMethod = (Method) ((MethodInfoImpl) method).reflection; + + // verify that the `methodInfo` belongs to this bean + if (!ReflectionMembers.allMethods(cdiBean.getBeanClass()).contains(reflectionMethod)) { + throw new DeploymentException("Method does not belong to bean " + cdiBean.getBeanClass().getName() + + ": " + method); + } + + AnnotatedType cdiBeanClass = ((ClassBean) cdiBean).getAnnotated(); + AnnotatedMethod cdiMethod = (AnnotatedMethod) ((MethodInfoImpl) method).cdiDeclaration; + TargetMethod targetMethod = cdiMethod != null ? new TargetMethod(cdiMethod) : new TargetMethod(reflectionMethod); + return new InvokerInfoBuilder<>(cdiBeanClass, targetMethod, beanManager); + } else { + throw new DeploymentException("Custom implementations of MethodInfo are not supported!"); + } + } +} diff --git a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ReflectionMembers.java b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ReflectionMembers.java index 6d22d80a51..3712f8ac16 100644 --- a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ReflectionMembers.java +++ b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/ReflectionMembers.java @@ -1,5 +1,7 @@ package org.jboss.weld.lite.extension.translator; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.ArrayDeque; import java.util.Arrays; import java.util.HashSet; @@ -20,7 +22,10 @@ private ReflectionMembers() { static Set allMethods(Class clazz) { return cachedMethods.computeIfAbsent(clazz, ignored -> { Set result = new HashSet<>(); - forEachSuperclass(clazz, it -> result.addAll(Arrays.asList(it.getDeclaredMethods()))); + forEachSuperclass(clazz, it -> { + Method[] methods = SecurityActions.getDeclaredMethods(it); + result.addAll(Arrays.asList(methods)); + }); return result; }); } @@ -28,7 +33,10 @@ static Set allMethods(Class clazz) { static Set allFields(Class clazz) { return cachedFields.computeIfAbsent(clazz, ignored -> { Set result = new HashSet<>(); - forEachSuperclass(clazz, it -> result.addAll(Arrays.asList(it.getDeclaredFields()))); + forEachSuperclass(clazz, it -> { + Field[] fields = SecurityActions.getDeclaredFields(it); + result.addAll(Arrays.asList(fields)); + }); return result; }); } diff --git a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/SecurityActions.java b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/SecurityActions.java index 58f511b60b..c713dc73f2 100644 --- a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/SecurityActions.java +++ b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/SecurityActions.java @@ -19,6 +19,8 @@ import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; @@ -26,6 +28,8 @@ import org.jboss.weld.exceptions.WeldException; import org.jboss.weld.security.GetConstructorAction; import org.jboss.weld.security.GetDeclaredConstructorsAction; +import org.jboss.weld.security.GetDeclaredFieldsAction; +import org.jboss.weld.security.GetDeclaredMethodsAction; import org.jboss.weld.security.SetAccessibleAction; import org.jboss.weld.util.reflection.Reflections; @@ -75,4 +79,20 @@ static Constructor[] getDeclaredConstructors(Class javaClass) { } } + static Method[] getDeclaredMethods(Class javaClass) { + if (System.getSecurityManager() != null) { + return Reflections.cast(AccessController.doPrivileged(new GetDeclaredMethodsAction(javaClass))); + } else { + return Reflections.cast(javaClass.getDeclaredMethods()); + } + } + + static Field[] getDeclaredFields(Class javaClass) { + if (System.getSecurityManager() != null) { + return Reflections.cast(AccessController.doPrivileged(new GetDeclaredFieldsAction(javaClass))); + } else { + return Reflections.cast(javaClass.getDeclaredFields()); + } + } + } From 5768bde3ca004213dd63d3b931cdb827eaf413c3 Mon Sep 17 00:00:00 2001 From: Matej Novotny Date: Tue, 23 Jan 2024 14:42:57 +0100 Subject: [PATCH 2/4] WELD-2774 Implement BM methods for event/bean assignability --- .../weld/bean/builtin/BeanManagerProxy.java | 12 +++ .../BeanAttributesConfiguratorImpl.java | 27 +----- .../jboss/weld/logging/BeanManagerLogger.java | 9 ++ .../jboss/weld/manager/BeanManagerImpl.java | 84 ++++++++++++++++--- .../java/org/jboss/weld/util/Bindings.java | 31 +++++++ 5 files changed, 125 insertions(+), 38 deletions(-) diff --git a/impl/src/main/java/org/jboss/weld/bean/builtin/BeanManagerProxy.java b/impl/src/main/java/org/jboss/weld/bean/builtin/BeanManagerProxy.java index 6148633fe5..30a44e88f5 100644 --- a/impl/src/main/java/org/jboss/weld/bean/builtin/BeanManagerProxy.java +++ b/impl/src/main/java/org/jboss/weld/bean/builtin/BeanManagerProxy.java @@ -192,6 +192,18 @@ public WeldInstance createInstance() { return delegate().createInstance(); } + @Override + public boolean isMatchingBean(Set beanTypes, Set beanQualifiers, Type requiredType, + Set requiredQualifiers) { + return delegate().isMatchingBean(beanTypes, beanQualifiers, requiredType, requiredQualifiers); + } + + @Override + public boolean isMatchingEvent(Type eventType, Set eventQualifiers, Type observedEventType, + Set observedEventQualifiers) { + return delegate().isMatchingEvent(eventType, eventQualifiers, observedEventType, observedEventQualifiers); + } + @Override public Bean getPassivationCapableBean(BeanIdentifier identifier) { return delegate().getPassivationCapableBean(identifier); diff --git a/impl/src/main/java/org/jboss/weld/bootstrap/events/configurator/BeanAttributesConfiguratorImpl.java b/impl/src/main/java/org/jboss/weld/bootstrap/events/configurator/BeanAttributesConfiguratorImpl.java index bc8149b45d..ea890057f7 100644 --- a/impl/src/main/java/org/jboss/weld/bootstrap/events/configurator/BeanAttributesConfiguratorImpl.java +++ b/impl/src/main/java/org/jboss/weld/bootstrap/events/configurator/BeanAttributesConfiguratorImpl.java @@ -25,7 +25,6 @@ import java.util.Set; import jakarta.enterprise.context.Dependent; -import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.enterprise.inject.spi.BeanAttributes; import jakarta.enterprise.inject.spi.configurator.BeanAttributesConfigurator; @@ -222,7 +221,8 @@ public BeanAttributesConfigurator alternative(boolean alternative) { @Override public BeanAttributes complete() { - return new ImmutableBeanAttributes(ImmutableSet.copyOf(stereotypes), isAlternative, name, initQualifiers(qualifiers), + return new ImmutableBeanAttributes(ImmutableSet.copyOf(stereotypes), isAlternative, name, + Bindings.normalizeBeanQualifiers(qualifiers), ImmutableSet.copyOf(types), initScope()); } @@ -258,27 +258,4 @@ private Class initScope() { return Dependent.class; } - private Set initQualifiers(Set qualifiers) { - if (qualifiers.isEmpty()) { - return Bindings.DEFAULT_QUALIFIERS; - } - Set normalized = new HashSet(qualifiers); - normalized.remove(Any.Literal.INSTANCE); - normalized.remove(Default.Literal.INSTANCE); - if (normalized.isEmpty()) { - normalized = Bindings.DEFAULT_QUALIFIERS; - } else { - ImmutableSet.Builder builder = ImmutableSet.builder(); - if (normalized.size() == 1) { - if (normalized.iterator().next().annotationType().equals(Named.class)) { - builder.add(Default.Literal.INSTANCE); - } - } - builder.add(Any.Literal.INSTANCE); - builder.addAll(qualifiers); - normalized = builder.build(); - } - return normalized; - } - } diff --git a/impl/src/main/java/org/jboss/weld/logging/BeanManagerLogger.java b/impl/src/main/java/org/jboss/weld/logging/BeanManagerLogger.java index c21c50be87..bfbf1df8ee 100644 --- a/impl/src/main/java/org/jboss/weld/logging/BeanManagerLogger.java +++ b/impl/src/main/java/org/jboss/weld/logging/BeanManagerLogger.java @@ -128,4 +128,13 @@ public interface BeanManagerLogger extends WeldLogger { @Message(id = 1336, value = "InjectionTargetFactory.configure() may not be called after createInjectionTarget() invocation. AnnotatedType used: {0}", format = Format.MESSAGE_FORMAT) IllegalStateException unableToConfigureInjectionTargetFactory(Object param1); + @Message(id = 1337, value = "BeanContainer#{0} requires all parameters to be non-null.", format = Format.MESSAGE_FORMAT) + IllegalArgumentException assignabilityMethodIllegalArgs(Object param1); + + @Message(id = 1338, value = "All annotations passed into BeanContainer#{0} have to be CDI Qualifiers. Following annotation was not recognized as a qualifier: {1}", format = Format.MESSAGE_FORMAT) + IllegalArgumentException annotationNotAQualifier(Object param1, Object param2); + + @Message(id = 1339, value = "Provided event type {0} cannot contain unresolvable type parameter", format = Format.MESSAGE_FORMAT) + IllegalArgumentException eventTypeUnresolvableWildcard(Object param1); + } \ No newline at end of file diff --git a/impl/src/main/java/org/jboss/weld/manager/BeanManagerImpl.java b/impl/src/main/java/org/jboss/weld/manager/BeanManagerImpl.java index d797bfa0f6..2aee2a2bd7 100644 --- a/impl/src/main/java/org/jboss/weld/manager/BeanManagerImpl.java +++ b/impl/src/main/java/org/jboss/weld/manager/BeanManagerImpl.java @@ -53,6 +53,8 @@ import jakarta.enterprise.context.spi.Contextual; import jakarta.enterprise.context.spi.CreationalContext; import jakarta.enterprise.event.Event; +import jakarta.enterprise.inject.Any; +import jakarta.enterprise.inject.Default; import jakarta.enterprise.inject.Instance; import jakarta.enterprise.inject.spi.Annotated; import jakarta.enterprise.inject.spi.AnnotatedField; @@ -128,7 +130,6 @@ import org.jboss.weld.exceptions.IllegalArgumentException; import org.jboss.weld.exceptions.IllegalStateException; import org.jboss.weld.exceptions.InjectionException; -import org.jboss.weld.exceptions.UnsupportedOperationException; import org.jboss.weld.inject.WeldInstance; import org.jboss.weld.injection.CurrentInjectionPoint; import org.jboss.weld.injection.EmptyInjectionPoint; @@ -156,6 +157,7 @@ import org.jboss.weld.module.ObserverNotifierFactory; import org.jboss.weld.resolution.BeanTypeAssignabilityRules; import org.jboss.weld.resolution.DecoratorResolvableBuilder; +import org.jboss.weld.resolution.EventTypeAssignabilityRules; import org.jboss.weld.resolution.InterceptorResolvable; import org.jboss.weld.resolution.InterceptorResolvableBuilder; import org.jboss.weld.resolution.NameBasedResolver; @@ -179,9 +181,11 @@ import org.jboss.weld.util.LazyValueHolder; import org.jboss.weld.util.Observers; import org.jboss.weld.util.Preconditions; +import org.jboss.weld.util.Types; import org.jboss.weld.util.collections.ImmutableSet; import org.jboss.weld.util.collections.SetMultimap; import org.jboss.weld.util.collections.WeldCollections; +import org.jboss.weld.util.reflection.HierarchyDiscovery; import org.jboss.weld.util.reflection.Reflections; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -1580,6 +1584,72 @@ public WeldInstance createInstance() { return getInstance(createCreationalContext(null)); } + @Override + public boolean isMatchingBean(Set beanTypes, Set beanQualifiers, Type requiredType, + Set requiredQualifiers) { + String loggingMethodName = "isMatchingBean()"; + if (beanTypes == null || beanQualifiers == null || requiredType == null || requiredQualifiers == null) { + throw BeanManagerLogger.LOG.assignabilityMethodIllegalArgs(loggingMethodName); + } + validateQualifiers(beanQualifiers, loggingMethodName); + validateQualifiers(requiredQualifiers, loggingMethodName); + // always add Object as bean type; filter bean types to only contain legal bean types + Set legalBeanTypes = new HashSet<>(beanTypes); + legalBeanTypes.add(Object.class); + legalBeanTypes = Beans.getLegalBeanTypes(legalBeanTypes, beanTypes); + // type check first + if (BeanTypeAssignabilityRules.instance().matches(requiredType, legalBeanTypes)) { + // normalize qualifiers, adding built-ins where missing, then compare + Set normalizedBeanQualifiers = Bindings.normalizeBeanQualifiers(beanQualifiers); + Set normalizedRequiredQualifiers = requiredQualifiers.isEmpty() ? Set.of(Default.Literal.INSTANCE) + : requiredQualifiers; + MetaAnnotationStore metaAnnotationStore = services.get(MetaAnnotationStore.class); + if (Beans.containsAllQualifiers(QualifierInstance.of(normalizedRequiredQualifiers, metaAnnotationStore), + QualifierInstance.of(normalizedBeanQualifiers, metaAnnotationStore))) { + return true; + } + } + return false; + } + + @Override + public boolean isMatchingEvent(Type eventType, Set eventQualifiers, Type observedEventType, + Set observedEventQualifiers) { + String loggingMethodName = "isMatchingEvent()"; + if (eventType == null || eventQualifiers == null || observedEventType == null || observedEventQualifiers == null) { + throw BeanManagerLogger.LOG.assignabilityMethodIllegalArgs(loggingMethodName); + } + if (Types.containsTypeVariable(Types.getCanonicalType(eventType))) { + throw BeanManagerLogger.LOG.eventTypeUnresolvableWildcard(eventType); + } + validateQualifiers(eventQualifiers, loggingMethodName); + validateQualifiers(observedEventQualifiers, loggingMethodName); + // type check first + if (EventTypeAssignabilityRules.instance().matches(observedEventType, + HierarchyDiscovery.forNormalizedType(eventType).getTypeClosure())) { + // normalize qualifiers, adding built-ins where missing, then compare + Set normalizedEventQualifiers = new HashSet<>(eventQualifiers); + if (eventQualifiers.isEmpty()) { + normalizedEventQualifiers.add(Default.Literal.INSTANCE); + } + normalizedEventQualifiers.add(Any.Literal.INSTANCE); + MetaAnnotationStore metaAnnotationStore = services.get(MetaAnnotationStore.class); + if (Beans.containsAllQualifiers(QualifierInstance.of(observedEventQualifiers, metaAnnotationStore), + QualifierInstance.of(normalizedEventQualifiers, metaAnnotationStore))) { + return true; + } + } + return false; + } + + private void validateQualifiers(Set qualifiers, String methodName) { + for (Annotation qualifierCandidate : qualifiers) { + if (!isQualifier(qualifierCandidate.annotationType())) { + throw BeanManagerLogger.LOG.annotationNotAQualifier(methodName, qualifierCandidate.annotationType()); + } + } + } + private Bean findNormalScopedDependant(CreationalContextImpl weldCreationalContext) { CreationalContextImpl parent = weldCreationalContext.getParentCreationalContext(); if (parent != null) { @@ -1784,16 +1854,4 @@ private WeldUnusedMetadataExtension getUnusedMetadataExtension() { return null; } } - - @Override - public boolean isMatchingBean(Set beanTypes, Set beanQualifiers, Type requiredType, - Set requiredQualifiers) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isMatchingEvent(Type eventType, Set eventQualifiers, Type observedEventType, - Set observedEventQualifiers) { - throw new UnsupportedOperationException(); - } } diff --git a/impl/src/main/java/org/jboss/weld/util/Bindings.java b/impl/src/main/java/org/jboss/weld/util/Bindings.java index 7d03970808..fc8d95d598 100644 --- a/impl/src/main/java/org/jboss/weld/util/Bindings.java +++ b/impl/src/main/java/org/jboss/weld/util/Bindings.java @@ -17,11 +17,13 @@ package org.jboss.weld.util; import java.lang.annotation.Annotation; +import java.util.HashSet; import java.util.Set; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.inject.Named; import org.jboss.weld.logging.BeanManagerLogger; import org.jboss.weld.logging.MetadataLogger; @@ -102,4 +104,33 @@ private static void checkInterceptorBinding(Annotation qualifier, MetaAnnotation throw BeanManagerLogger.LOG.interceptorResolutionWithNonbindingType(qualifier); } } + + /** + * Normalize set of qualifiers for a bean - automatically adds {@code @Any} and {@code Default} if needed. + * + * @param qualifiers input set of qualifiers, possibly missing built-in qualifiers + * @return normalized set of bean qualifiers + */ + public static Set normalizeBeanQualifiers(Set qualifiers) { + if (qualifiers.isEmpty()) { + return DEFAULT_QUALIFIERS; + } + Set normalized = new HashSet(qualifiers); + normalized.remove(Any.Literal.INSTANCE); + normalized.remove(Default.Literal.INSTANCE); + if (normalized.isEmpty()) { + normalized = DEFAULT_QUALIFIERS; + } else { + ImmutableSet.Builder builder = ImmutableSet.builder(); + if (normalized.size() == 1) { + if (normalized.iterator().next().annotationType().equals(Named.class)) { + builder.add(Default.Literal.INSTANCE); + } + } + builder.add(Any.Literal.INSTANCE); + builder.addAll(qualifiers); + normalized = builder.build(); + } + return normalized; + } } From a8699559d72a818e54bc780f3fdbbe9d2fb3279d Mon Sep 17 00:00:00 2001 From: Matej Novotny Date: Sun, 25 Feb 2024 11:52:16 +0100 Subject: [PATCH 3/4] Update Weld parent to version 49 Keep TCK version at M1 - it is the latest released ATM Update Weld API to Beta1 --- bom/pom.xml | 2 +- pom.xml | 21 ++++----------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/bom/pom.xml b/bom/pom.xml index 64b4c472d5..641011c52d 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -30,7 +30,7 @@ - 6.0.Alpha2 + 6.0.Beta2 3.0.1 https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/ https://repository.jboss.org/nexus/content/repositories/snapshots/ diff --git a/pom.xml b/pom.xml index 08e9c2b170..5ee4bff679 100644 --- a/pom.xml +++ b/pom.xml @@ -10,11 +10,11 @@ org.jboss.weld weld-parent - 47 + 49 - 3.0 + 3.8 @@ -60,7 +60,7 @@ 1.2.0.Final 2.0.1 - 4.1.0-SNAPSHOT + 4.1.0-M1 @@ -89,7 +89,7 @@ 2.0.0 3.3.0 7.9.0 - 6.0-SNAPSHOT + 6.0.Beta2 1.0.3.Final 5.0.1.Final @@ -727,17 +727,4 @@ - - - - - jboss-public-repository-group - JBoss Public Repository Group - https://repository.jboss.org/nexus/content/groups/public - default - - true - - - From c60a0afa82c5baf5319ac6c6fc9378c9602d2b8d Mon Sep 17 00:00:00 2001 From: Matej Novotny Date: Sun, 25 Feb 2024 13:59:13 +0100 Subject: [PATCH 4/4] Update CDI API version in the WFLY update script --- jboss-as/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jboss-as/pom.xml b/jboss-as/pom.xml index f2e1e3e724..7501a2028a 100644 --- a/jboss-as/pom.xml +++ b/jboss-as/pom.xml @@ -32,7 +32,7 @@ as the release plugin won't deal with double evaluation --> 6.0.0-SNAPSHOT - 4.1.0-M1 + 4.1.0.Beta1 2.2.0-RC1