-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #37302 from Ladicek/bean-enablement-on-stereotypes
ArC: allow putting bean enablement annotations on stereotypes
- Loading branch information
Showing
13 changed files
with
1,540 additions
and
137 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
396 changes: 263 additions & 133 deletions
396
...ons/arc/deployment/src/main/java/io/quarkus/arc/deployment/BuildTimeEnabledProcessor.java
Large diffs are not rendered by default.
Oops, something went wrong.
53 changes: 53 additions & 0 deletions
53
...loyment/src/main/java/io/quarkus/arc/deployment/BuildTimeEnabledStereotypesBuildItem.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package io.quarkus.arc.deployment; | ||
|
||
import java.util.Collection; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import org.jboss.jandex.AnnotationInstance; | ||
import org.jboss.jandex.DotName; | ||
|
||
import io.quarkus.builder.item.SimpleBuildItem; | ||
|
||
final class BuildTimeEnabledStereotypesBuildItem extends SimpleBuildItem { | ||
private final Map<DotName, BuildTimeEnabledStereotype> map; | ||
|
||
BuildTimeEnabledStereotypesBuildItem(List<BuildTimeEnabledStereotype> buildTimeEnabledStereotypes) { | ||
Map<DotName, BuildTimeEnabledStereotype> map = new HashMap<>(); | ||
for (BuildTimeEnabledStereotype buildTimeEnabledStereotype : buildTimeEnabledStereotypes) { | ||
map.put(buildTimeEnabledStereotype.name, buildTimeEnabledStereotype); | ||
} | ||
this.map = map; | ||
} | ||
|
||
boolean isStereotype(DotName name) { | ||
return map.containsKey(name); | ||
} | ||
|
||
BuildTimeEnabledStereotype getStereotype(DotName stereotypeName) { | ||
return map.get(stereotypeName); | ||
} | ||
|
||
Collection<BuildTimeEnabledStereotype> all() { | ||
return map.values(); | ||
} | ||
|
||
static final class BuildTimeEnabledStereotype { | ||
final DotName name; | ||
final boolean inheritable; // meta-annotated `@Inherited` | ||
|
||
// enablement annotations present directly _or transitively_ on this stereotype | ||
final Map<DotName, List<AnnotationInstance>> annotations; | ||
|
||
BuildTimeEnabledStereotype(DotName name, boolean inheritable, Map<DotName, List<AnnotationInstance>> annotations) { | ||
this.name = name; | ||
this.inheritable = inheritable; | ||
this.annotations = annotations; | ||
} | ||
|
||
List<AnnotationInstance> getEnablementAnnotations(DotName enablementAnnotationName) { | ||
return annotations.getOrDefault(enablementAnnotationName, List.of()); | ||
} | ||
} | ||
} |
195 changes: 195 additions & 0 deletions
195
...rc/deployment/src/test/java/io/quarkus/arc/test/profile/IfBuildProfileStereotypeTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
package io.quarkus.arc.test.profile; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Inherited; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
|
||
import jakarta.enterprise.context.ApplicationScoped; | ||
import jakarta.enterprise.inject.Any; | ||
import jakarta.enterprise.inject.Instance; | ||
import jakarta.enterprise.inject.Produces; | ||
import jakarta.enterprise.inject.Stereotype; | ||
import jakarta.inject.Inject; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.RegisterExtension; | ||
|
||
import io.quarkus.arc.profile.IfBuildProfile; | ||
import io.quarkus.test.QuarkusUnitTest; | ||
|
||
public class IfBuildProfileStereotypeTest { | ||
@RegisterExtension | ||
static final QuarkusUnitTest config = new QuarkusUnitTest() | ||
.withApplicationRoot((jar) -> jar | ||
.addClasses(DevOnly.class, InheritableDevOnly.class, TransitiveDevOnly.class, | ||
InheritableTransitiveDevOnly.class, MyService.class, DevOnlyMyService.class, | ||
InheritableDevOnlyMyService.class, TransitiveDevOnlyMyService.class, | ||
InheritableTransitiveDevOnlyMyService.class, MyServiceSimple.class, | ||
MyServiceDevOnlyDirect.class, MyServiceDevOnlyTransitive.class, | ||
MyServiceDevOnlyOnSuperclassNotInheritable.class, | ||
MyServiceDevOnlyOnSuperclassInheritable.class, | ||
MyServiceDevOnlyTransitiveOnSuperclassNotInheritable.class, | ||
MyServiceDevOnlyTransitiveOnSuperclassInheritable.class, Producers.class)); | ||
|
||
@Inject | ||
@Any | ||
Instance<MyService> services; | ||
|
||
@Test | ||
public void test() { | ||
Set<String> hello = services.stream().map(MyService::hello).collect(Collectors.toSet()); | ||
Set<Object> expected = Set.of( | ||
MyServiceSimple.class.getSimpleName(), | ||
MyServiceDevOnlyOnSuperclassNotInheritable.class.getSimpleName(), | ||
MyServiceDevOnlyTransitiveOnSuperclassNotInheritable.class.getSimpleName(), | ||
Producers.SIMPLE); | ||
assertEquals(expected, hello); | ||
} | ||
|
||
@IfBuildProfile("dev") | ||
@Stereotype | ||
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface DevOnly { | ||
} | ||
|
||
@IfBuildProfile("dev") | ||
@Stereotype | ||
@Inherited | ||
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface InheritableDevOnly { | ||
} | ||
|
||
@DevOnly | ||
@Stereotype | ||
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface TransitiveDevOnly { | ||
} | ||
|
||
@DevOnly | ||
@Stereotype | ||
@Inherited | ||
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface InheritableTransitiveDevOnly { | ||
} | ||
|
||
interface MyService { | ||
String hello(); | ||
} | ||
|
||
@DevOnly | ||
static abstract class DevOnlyMyService implements MyService { | ||
} | ||
|
||
@InheritableDevOnly | ||
static abstract class InheritableDevOnlyMyService implements MyService { | ||
} | ||
|
||
@TransitiveDevOnly | ||
static abstract class TransitiveDevOnlyMyService implements MyService { | ||
} | ||
|
||
@InheritableTransitiveDevOnly | ||
static abstract class InheritableTransitiveDevOnlyMyService implements MyService { | ||
} | ||
|
||
@ApplicationScoped | ||
static class MyServiceSimple implements MyService { | ||
@Override | ||
public String hello() { | ||
return MyServiceSimple.class.getSimpleName(); | ||
} | ||
} | ||
|
||
@ApplicationScoped | ||
@DevOnly | ||
static class MyServiceDevOnlyDirect implements MyService { | ||
@Override | ||
public String hello() { | ||
return MyServiceDevOnlyDirect.class.getSimpleName(); | ||
} | ||
} | ||
|
||
@ApplicationScoped | ||
@TransitiveDevOnly | ||
static class MyServiceDevOnlyTransitive implements MyService { | ||
@Override | ||
public String hello() { | ||
return MyServiceDevOnlyTransitive.class.getSimpleName(); | ||
} | ||
} | ||
|
||
@ApplicationScoped | ||
static class MyServiceDevOnlyOnSuperclassNotInheritable extends DevOnlyMyService { | ||
@Override | ||
public String hello() { | ||
return MyServiceDevOnlyOnSuperclassNotInheritable.class.getSimpleName(); | ||
} | ||
} | ||
|
||
@ApplicationScoped | ||
static class MyServiceDevOnlyOnSuperclassInheritable extends InheritableDevOnlyMyService { | ||
@Override | ||
public String hello() { | ||
return MyServiceDevOnlyOnSuperclassInheritable.class.getSimpleName(); | ||
} | ||
} | ||
|
||
@ApplicationScoped | ||
static class MyServiceDevOnlyTransitiveOnSuperclassNotInheritable extends TransitiveDevOnlyMyService { | ||
@Override | ||
public String hello() { | ||
return MyServiceDevOnlyTransitiveOnSuperclassNotInheritable.class.getSimpleName(); | ||
} | ||
} | ||
|
||
@ApplicationScoped | ||
static class MyServiceDevOnlyTransitiveOnSuperclassInheritable extends InheritableTransitiveDevOnlyMyService { | ||
@Override | ||
public String hello() { | ||
return MyServiceDevOnlyTransitiveOnSuperclassInheritable.class.getSimpleName(); | ||
} | ||
} | ||
|
||
@ApplicationScoped | ||
static class Producers { | ||
static final String SIMPLE = "Producers.simple"; | ||
static final String DEV_ONLY_DIRECT = "Producers.devOnlyDirect"; | ||
static final String DEV_ONLY_TRANSITIVE = "Producers.devOnlyTransitive"; | ||
|
||
@Produces | ||
MyService simple = new MyService() { | ||
@Override | ||
public String hello() { | ||
return SIMPLE; | ||
} | ||
}; | ||
|
||
@Produces | ||
@DevOnly | ||
MyService devOnlyDirect = new MyService() { | ||
@Override | ||
public String hello() { | ||
return DEV_ONLY_DIRECT; | ||
} | ||
}; | ||
|
||
@Produces | ||
@TransitiveDevOnly | ||
MyService devOnlyTransitive = new MyService() { | ||
@Override | ||
public String hello() { | ||
return DEV_ONLY_TRANSITIVE; | ||
} | ||
}; | ||
} | ||
} |
Oops, something went wrong.