Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arc - support static producer methods. #5516

Merged
merged 1 commit into from
Nov 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1119,25 +1119,31 @@ protected void implementCreate(ClassOutput classOutput, ClassCreator beanCreator
create.returnValue(instanceHandle);

} else if (bean.isProducerMethod()) {
MethodInfo producerMethod = bean.getTarget().get().asMethod();
instanceHandle = create.createVariable(DescriptorUtils.extToInt(providerTypeName));
// instance = declaringProviderSupplier.get().get(new CreationalContextImpl<>()).produce()
ResultHandle ctxHandle = create.newInstance(
MethodDescriptor.ofConstructor(CreationalContextImpl.class, Contextual.class), create.getThis());
ResultHandle declaringProviderInstanceHandle;
ResultHandle declaringProviderSupplierHandle = create.readInstanceField(
FieldDescriptor.of(beanCreator.getClassName(), FIELD_NAME_DECLARING_PROVIDER_SUPPLIER,
Supplier.class.getName()),
create.getThis());
ResultHandle declaringProviderHandle = create.invokeInterfaceMethod(
MethodDescriptors.SUPPLIER_GET, declaringProviderSupplierHandle);
ResultHandle ctxHandle = create.newInstance(
MethodDescriptor.ofConstructor(CreationalContextImpl.class, Contextual.class), create.getThis());
ResultHandle declaringProviderInstanceHandle = create.invokeInterfaceMethod(
MethodDescriptors.INJECTABLE_REF_PROVIDER_GET, declaringProviderHandle,
ctxHandle);

if (bean.getDeclaringBean().getScope().isNormal()) {
// We need to unwrap the client proxy
if (Modifier.isStatic(producerMethod.flags())) {
// for static producers, we don't need to resolve this this handle
declaringProviderInstanceHandle = create.loadNull();
} else {
declaringProviderInstanceHandle = create.invokeInterfaceMethod(
MethodDescriptors.CLIENT_PROXY_GET_CONTEXTUAL_INSTANCE,
declaringProviderInstanceHandle);
MethodDescriptors.INJECTABLE_REF_PROVIDER_GET, declaringProviderHandle,
ctxHandle);
if (bean.getDeclaringBean().getScope().isNormal()) {
// We need to unwrap the client proxy
declaringProviderInstanceHandle = create.invokeInterfaceMethod(
MethodDescriptors.CLIENT_PROXY_GET_CONTEXTUAL_INSTANCE,
declaringProviderInstanceHandle);
}
}

List<InjectionPointInfo> injectionPoints = bean.getAllInjectionPoints();
Expand All @@ -1156,7 +1162,6 @@ protected void implementCreate(ClassOutput classOutput, ClassCreator beanCreator
referenceHandles[paramIdx++] = referenceHandle;
}

MethodInfo producerMethod = bean.getTarget().get().asMethod();
if (Modifier.isPrivate(producerMethod.flags())) {
privateMembers.add(isApplicationClass, String.format("Producer method %s#%s()",
producerMethod.declaringClass().name(), producerMethod.name()));
Expand All @@ -1171,10 +1176,18 @@ protected void implementCreate(ClassOutput classOutput, ClassCreator beanCreator
create.assign(instanceHandle, create.invokeStaticMethod(MethodDescriptors.REFLECTIONS_INVOKE_METHOD,
create.loadClass(producerMethod.declaringClass().name().toString()), create.load(producerMethod.name()),
paramTypesArray,
declaringProviderInstanceHandle, argsArray));
declaringProviderInstanceHandle,
argsArray));
} else {
create.assign(instanceHandle, create.invokeVirtualMethod(MethodDescriptor.of(producerMethod),
declaringProviderInstanceHandle, referenceHandles));
ResultHandle invokeMethodHandle;
if (Modifier.isStatic(producerMethod.flags())) {
invokeMethodHandle = create.invokeStaticMethod(MethodDescriptor.of(producerMethod),
referenceHandles);
} else {
invokeMethodHandle = create.invokeVirtualMethod(MethodDescriptor.of(producerMethod),
declaringProviderInstanceHandle, referenceHandles);
}
create.assign(instanceHandle, invokeMethodHandle);
}

if (bean.getScope().isNormal()) {
Expand Down Expand Up @@ -1205,15 +1218,20 @@ protected void implementCreate(ClassOutput classOutput, ClassCreator beanCreator
MethodDescriptors.SUPPLIER_GET, declaringProviderSupplierHandle);
ResultHandle ctxHandle = create.newInstance(
MethodDescriptor.ofConstructor(CreationalContextImpl.class, Contextual.class), create.getThis());
ResultHandle declaringProviderInstanceHandle = create.invokeInterfaceMethod(
MethodDescriptors.INJECTABLE_REF_PROVIDER_GET, declaringProviderHandle,
ctxHandle);

if (bean.getDeclaringBean().getScope().isNormal()) {
// We need to unwrap the client proxy
ResultHandle declaringProviderInstanceHandle;
if (Modifier.isStatic(producerField.flags())) {
declaringProviderInstanceHandle = create.loadNull();
} else {
declaringProviderInstanceHandle = create.invokeInterfaceMethod(
MethodDescriptors.CLIENT_PROXY_GET_CONTEXTUAL_INSTANCE,
declaringProviderInstanceHandle);
MethodDescriptors.INJECTABLE_REF_PROVIDER_GET, declaringProviderHandle,
ctxHandle);

if (bean.getDeclaringBean().getScope().isNormal()) {
// We need to unwrap the client proxy
declaringProviderInstanceHandle = create.invokeInterfaceMethod(
MethodDescriptors.CLIENT_PROXY_GET_CONTEXTUAL_INSTANCE,
declaringProviderInstanceHandle);
}
}

if (Modifier.isPrivate(producerField.flags())) {
Expand All @@ -1224,8 +1242,14 @@ protected void implementCreate(ClassOutput classOutput, ClassCreator beanCreator
create.loadClass(producerField.declaringClass().name().toString()), create.load(producerField.name()),
declaringProviderInstanceHandle));
} else {
create.assign(instanceHandle,
create.readInstanceField(FieldDescriptor.of(producerField), declaringProviderInstanceHandle));
ResultHandle readFieldHandle;
if (Modifier.isStatic(producerField.flags())) {
readFieldHandle = create.readStaticField(FieldDescriptor.of(producerField));
} else {
readFieldHandle = create.readInstanceField(FieldDescriptor.of(producerField),
declaringProviderInstanceHandle);
}
create.assign(instanceHandle, readFieldHandle);
}

if (bean.getScope().isNormal()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package io.quarkus.arc.test.producer.staticProducers;

import io.quarkus.arc.Arc;
import io.quarkus.arc.InstanceHandle;
import io.quarkus.arc.test.ArcTestContainer;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.enterprise.inject.Produces;
import javax.enterprise.util.AnnotationLiteral;
import javax.inject.Qualifier;
import javax.inject.Singleton;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

/**
* Tests static method/field producers
*/
public class StaticMethodProducerTest {

@RegisterExtension
public ArcTestContainer container = new ArcTestContainer(StaticMethodProducerTest.class, SomeProducer.class,
MyQualifier.class);

@Test
public void testStaticProducers() {
// method producers
InstanceHandle<String> stringMethod = Arc.container().instance(String.class);
Assertions.assertTrue(stringMethod.isAvailable());
Assertions.assertEquals("foo", stringMethod.get());
InstanceHandle<Long> longMethod = Arc.container().instance(Long.class);
Assertions.assertTrue(longMethod.isAvailable());
Assertions.assertEquals(2L, longMethod.get());
InstanceHandle<Double> doubleMethod = Arc.container().instance(Double.class);
Assertions.assertTrue(doubleMethod.isAvailable());
Assertions.assertEquals(2.1, doubleMethod.get());

// field producers
InstanceHandle<String> stringField = Arc.container().instance(String.class, MyQualifier.Literal.INSTANCE);
Assertions.assertTrue(stringField.isAvailable());
Assertions.assertEquals("foo", stringField.get());
InstanceHandle<Long> longField = Arc.container().instance(Long.class, MyQualifier.Literal.INSTANCE);
Assertions.assertTrue(longField.isAvailable());
Assertions.assertEquals(2L, longField.get());
InstanceHandle<Double> doubleField = Arc.container().instance(Double.class, MyQualifier.Literal.INSTANCE);
Assertions.assertTrue(doubleField.isAvailable());
Assertions.assertEquals(2.1, doubleField.get());
}

@Singleton
static class SomeProducer {

static Long LONG = 2l;
static String STRING = "foo";
static Double DOUBLE = 2.1;

@Produces
private static Long produceLong() {
return LONG;
}

@Produces
static String produceString() {
return STRING;
}

@Produces
public static Double produceDouble() {
return DOUBLE;
}

@Produces
@MyQualifier
private static Long longField = LONG;

@Produces
@MyQualifier
static String stringField = STRING;

@Produces
@MyQualifier
public static Double doubleField = DOUBLE;
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.METHOD })
static @interface MyQualifier {
public final static class Literal extends AnnotationLiteral<MyQualifier> implements MyQualifier {

public static final Literal INSTANCE = new Literal();
private static final long serialVersionUID = 1L;

}
}
}