Skip to content

Commit

Permalink
Issue #281: added support for jakarta.inject namespace (#284)
Browse files Browse the repository at this point in the history
  • Loading branch information
raner authored Mar 18, 2024
1 parent e714413 commit 8fd12e3
Show file tree
Hide file tree
Showing 16 changed files with 703 additions and 17 deletions.
7 changes: 6 additions & 1 deletion projo-runtime-code-generation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,15 @@
<version>1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jakarta.inject</groupId>
<artifactId>jakarta.inject-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.2.2</version>
<version>6.0.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// //
// Copyright 2017 - 2023 Mirko Raner //
// Copyright 2017 - 2024 Mirko Raner //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
Expand Down Expand Up @@ -126,8 +126,6 @@ public class RuntimeCodeGenerationHandler<_Artifact_> extends ProjoHandler<_Arti
private Map<Class<_Artifact_>, Class<? extends _Artifact_>> implementationClassCache =
new ConcurrentHashMap<>();

private final String injected = "javax.inject.Inject";

private final static String SUFFIX = "$Projo";

private static Map<List<Boolean>, Class<?>> baseClasses = new HashMap<>();
Expand Down Expand Up @@ -320,7 +318,7 @@ private Builder<_Artifact_> add(Builder<_Artifact_> builder, Method method, List
String methodName = annotations.get(Overrides.class).map(Overrides::value).orElse(method.getName());
String propertyName = matcher.propertyName(methodName);
UnaryOperator<Builder<_Artifact_>> addFieldForGetter;
Optional<Annotation> inject = annotations.get(injected);
Optional<Annotation> inject = annotations.getInject();
Class<?> returnType = method.getReturnType();
TypeDescription.Generic type = isGetter? getFieldType(annotations, returnType, classLoader):VOID.asGenericType();
addFieldForGetter = isGetter? localBuilder -> annotate(inject, localBuilder.defineField(propertyName, type, PRIVATE)):identity();
Expand Down Expand Up @@ -369,9 +367,10 @@ private Builder<_Artifact_> add(Builder<_Artifact_> builder, Method method, List

Implementation getAccessor(Method method, AnnotationList annotations, Type returnType, String property, List<String> additionalImplements, ClassLoader classLoader)
{
if (annotations.contains(injected))
Optional<Annotation> inject;
if ((inject = annotations.getInject()).isPresent())
{
return get(property, returnType, classLoader);
return get(property, returnType, inject.get(), classLoader);
}
if (annotations.contains(Cached.class))
{
Expand Down Expand Up @@ -463,9 +462,9 @@ private Implementation cached(Cached cached, String field, Type type)
}
}

private Implementation get(String field, Type type, ClassLoader classLoader)
private Implementation get(String field, Type type, Annotation inject, ClassLoader classLoader)
{
Class<?> provider = Projo.forName("javax.inject.Provider", classLoader);
Class<?> provider = Projo.forName(provider(inject), classLoader);
Generic genericProvider = Generic.Builder.parameterizedType(provider, type).build();
MethodDescription get = latent(genericProvider.asErasure(), OBJECT.asGenericType(), "get");
return MethodCall.invoke(get).onField(field).withAssigner(DEFAULT, DYNAMIC);
Expand Down Expand Up @@ -501,13 +500,14 @@ private ByteBuddy codeGenerator()
**/
Generic getFieldType(AnnotationList annotations, Class<?> originalReturnType, ClassLoader classLoader)
{
if (!annotations.contains(injected) && !annotations.contains(Cached.class))
if (!annotations.containsInject() && !annotations.contains(Cached.class))
{
return Generic.Builder.rawType(originalReturnType).build();
}
else
{
Class<?> container = annotations.contains(injected)? Projo.forName("javax.inject.Provider", classLoader):Cache.class;
Optional<Class<?>> optionalContainer = annotations.getInject().map(inject -> Projo.forName(provider(inject), classLoader));
Class<?> container = optionalContainer.orElse(Cache.class);
Type wrappedType = MethodType.methodType(originalReturnType).wrap().returnType();
Optional<Returns> returns = annotations.get(Returns.class);
if (returns.isPresent())
Expand Down Expand Up @@ -535,6 +535,17 @@ Generic getFieldType(AnnotationList annotations, Class<?> originalReturnType, Cl
}
}

/**
* Returns the corresponding provider annotation name for an inject annotation.
*
* @param inject the {@code @Inject} annotation
* @return the fully qualified name of the corresponding {@code @Provider}
**/
private String provider(Annotation inject)
{
return inject.annotationType().getPackage().getName() + ".Provider";
}

private <_ValuableBuilder_ extends Valuable<_Artifact_> & Builder<_Artifact_>>
Builder<_Artifact_> annotate(Optional<Annotation> annotation, _ValuableBuilder_ builder)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// //
// Copyright 2019 Mirko Raner //
// Copyright 2019 - 2024 Mirko Raner //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
Expand Down Expand Up @@ -49,21 +49,25 @@ static interface Boolean

static interface True extends Boolean, Booleans
{
@Override
default Boolean or(Boolean other)
{
return TRUE();
}

@Override
default Boolean xor(Boolean other)
{
return other.not();
}

@Override
default Boolean and(Boolean other)
{
return other;
}

@Override
default Boolean not()
{
return FALSE();
Expand All @@ -72,21 +76,25 @@ default Boolean not()

static interface False extends Boolean, Booleans
{
@Override
default Boolean or(Boolean other)
{
return other;
}

@Override
default Boolean xor(Boolean other)
{
return other;
}

@Override
default Boolean and(Boolean other)
{
return FALSE();
}

@Override
default Boolean not()
{
return TRUE();
Expand Down Expand Up @@ -118,6 +126,7 @@ static class TestUnary extends TestData
this.expected = expected;
}

@Override
void test(Function<java.lang.Boolean, Boolean> converter)
{
Boolean object = converter.apply(left);
Expand All @@ -140,6 +149,7 @@ static class TestBinary extends TestData
this.expected = expected;
}

@Override
void test(Function<java.lang.Boolean, Boolean> converter)
{
Boolean object = converter.apply(left);
Expand Down Expand Up @@ -180,6 +190,7 @@ public void test() throws Exception
{
Module module = new AbstractModule()
{
@Override
protected void configure()
{
bind(True.class).to(Projo.getImplementationClass(True.class)).asEagerSingleton();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// //
// Copyright 2019 - 2022 Mirko Raner //
// Copyright 2019 - 2024 Mirko Raner //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
Expand Down Expand Up @@ -108,6 +108,7 @@ public void testThatPropertyAnnotationWorksInConjunctionWithInject() throws Exce
{
Module module = new AbstractModule()
{
@Override
protected void configure()
{
bind(True.class).to(Projo.getImplementationClass(True.class)).asEagerSingleton();
Expand All @@ -133,6 +134,7 @@ public void testThatReturnsAnnotationWorksInConjunctionWithInject() throws Excep

Module module = new AbstractModule()
{
@Override
@SuppressWarnings("unchecked")
protected void configure()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// //
// Copyright 2022 Mirko Raner //
// Copyright 2022 - 2024 Mirko Raner //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
Expand Down Expand Up @@ -112,6 +112,7 @@ private Module module(Literals literals)
{
return new AbstractModule()
{
@Override
@SuppressWarnings("unchecked")
protected void configure()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// //
// Copyright 2017 - 2023 Mirko Raner //
// Copyright 2017 - 2024 Mirko Raner //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
Expand All @@ -15,6 +15,7 @@
// //
package pro.projo.internal.rcg;

import java.lang.reflect.Method;
import javax.inject.Inject;
import org.junit.Test;
import net.bytebuddy.description.type.TypeDescription.Generic;
Expand Down Expand Up @@ -78,6 +79,17 @@ public void testFieldTypeForInjectedMethod() throws Exception
assertEquals("javax.inject.Provider<java.lang.String>", fieldType.toString());
}

@Test
@jakarta.inject.Inject
public void testFieldTypeForInjectedMethodJakarta() throws Exception
{
RuntimeCodeGenerationHandler<?> handler = new RuntimeCodeGenerationHandler<>();
Method declaredMethod = getClass().getDeclaredMethod("testFieldTypeForInjectedMethodJakarta");
jakarta.inject.Inject inject = declaredMethod.getAnnotation(jakarta.inject.Inject.class);
Generic fieldType = handler.getFieldType(new AnnotationList(inject), String.class, classLoader);
assertEquals("jakarta.inject.Provider<java.lang.String>", fieldType.toString());
}

@Test
@Cached
public void testFieldTypeForCachedMethod() throws Exception
Expand Down
Loading

0 comments on commit 8fd12e3

Please sign in to comment.