Skip to content

Commit

Permalink
Arc - support static producer methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
manovotn committed Nov 15, 2019
1 parent 3d5bbbd commit b55c59d
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 24 deletions.
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;

}
}
}

0 comments on commit b55c59d

Please sign in to comment.