From 416ab3fa6ddd3d3481e487c94c1fbcab56b4783b Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Wed, 1 Dec 2021 15:26:46 +0100 Subject: [PATCH 1/3] Avoid useless dependencies in the core TCK --- impl/pom.xml | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/impl/pom.xml b/impl/pom.xml index 151aa9dc6c..2d36981c68 100644 --- a/impl/pom.xml +++ b/impl/pom.xml @@ -70,22 +70,19 @@ jakarta.inject-api - - commons-httpclient - commons-httpclient - - - - net.sourceforge.htmlunit - htmlunit - - commons-lang commons-lang 2.2 test + + + commons-io + commons-io + 2.8.0 + test + @@ -424,20 +421,6 @@ - - - jdk9+ - - [9,) - - - - com.sun.xml.ws - jaxws-rt - 3.0.0-M3 - - - From df87cc36484e0cce46830a1a18f550089d84bf12 Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Wed, 1 Dec 2021 15:27:26 +0100 Subject: [PATCH 2/3] Add ability to skip adding beans.xml to the archive --- .../jboss/cdi/tck/shrinkwrap/ArchiveBuilder.java | 14 ++++++++++++++ .../cdi/tck/shrinkwrap/WebArchiveBuilder.java | 4 +++- .../shrinkwrap/ee/EnterpriseArchiveBuilder.java | 4 +++- .../cdi/tck/shrinkwrap/ee/WebArchiveBuilder.java | 4 +++- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/impl/src/main/java/org/jboss/cdi/tck/shrinkwrap/ArchiveBuilder.java b/impl/src/main/java/org/jboss/cdi/tck/shrinkwrap/ArchiveBuilder.java index 893cf76c2c..46c7c30229 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/shrinkwrap/ArchiveBuilder.java +++ b/impl/src/main/java/org/jboss/cdi/tck/shrinkwrap/ArchiveBuilder.java @@ -118,6 +118,8 @@ public abstract class ArchiveBuilder, A extends A protected BeansXml beansDescriptor = null; + protected boolean includeBeansXml = true; + protected ResourceDescriptor webXml = null; protected WebAppDescriptor webXmlDescriptor = null; @@ -190,6 +192,18 @@ public T withBeansXml(BeansXml beansDescriptor) { return self(); } + /** + * Suppresses adding the {@code beans.xml} descriptor to the archive. + * If this method is called, any previous or following calls to + * {@link #withBeansXml(String)} or {@link #withBeansXml(BeansXml)} are ignored. + * + * @return self + */ + public T withoutBeansXml() { + this.includeBeansXml = false; + return self(); + } + /** * Add CDI extension. This method does not add the specified extension class to the archive. * diff --git a/impl/src/main/java/org/jboss/cdi/tck/shrinkwrap/WebArchiveBuilder.java b/impl/src/main/java/org/jboss/cdi/tck/shrinkwrap/WebArchiveBuilder.java index 4dc7190701..a5a831bf49 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/shrinkwrap/WebArchiveBuilder.java +++ b/impl/src/main/java/org/jboss/cdi/tck/shrinkwrap/WebArchiveBuilder.java @@ -79,7 +79,9 @@ protected WebArchive buildInternal() { processResources(webArchive); // Deployment descriptors - webArchive.addAsWebInfResource(getBeansDescriptorAsset(), buildBeansDescriptorTargetPath(getBeansDescriptorTarget())); + if (includeBeansXml) { + webArchive.addAsWebInfResource(getBeansDescriptorAsset(), buildBeansDescriptorTargetPath(getBeansDescriptorTarget())); + } if (webXmlDescriptor != null) { webArchive.setWebXML(new StringAsset(webXmlDescriptor.exportAsString())); diff --git a/web/src/main/java/org/jboss/cdi/tck/shrinkwrap/ee/EnterpriseArchiveBuilder.java b/web/src/main/java/org/jboss/cdi/tck/shrinkwrap/ee/EnterpriseArchiveBuilder.java index 494dbf9dbe..979fbe69f8 100644 --- a/web/src/main/java/org/jboss/cdi/tck/shrinkwrap/ee/EnterpriseArchiveBuilder.java +++ b/web/src/main/java/org/jboss/cdi/tck/shrinkwrap/ee/EnterpriseArchiveBuilder.java @@ -129,7 +129,9 @@ protected EnterpriseArchive buildInternal() { processLibraries(enterpriseArchive); // Deployment descriptors - ejbArchive.addAsManifestResource(getBeansDescriptorAsset(), getBeansDescriptorTarget()); + if (includeBeansXml) { + ejbArchive.addAsManifestResource(getBeansDescriptorAsset(), getBeansDescriptorTarget()); + } if (persistenceDescriptor != null) { ejbArchive.addAsManifestResource(new StringAsset(persistenceDescriptor.exportAsString()), "persistence.xml"); diff --git a/web/src/main/java/org/jboss/cdi/tck/shrinkwrap/ee/WebArchiveBuilder.java b/web/src/main/java/org/jboss/cdi/tck/shrinkwrap/ee/WebArchiveBuilder.java index 585fce0a23..a741a151ed 100644 --- a/web/src/main/java/org/jboss/cdi/tck/shrinkwrap/ee/WebArchiveBuilder.java +++ b/web/src/main/java/org/jboss/cdi/tck/shrinkwrap/ee/WebArchiveBuilder.java @@ -94,7 +94,9 @@ protected WebArchive buildInternal() { processResources(webArchive); // Deployment descriptors - webArchive.addAsWebInfResource(getBeansDescriptorAsset(), buildBeansDescriptorTargetPath(getBeansDescriptorTarget())); + if (includeBeansXml) { + webArchive.addAsWebInfResource(getBeansDescriptorAsset(), buildBeansDescriptorTargetPath(getBeansDescriptorTarget())); + } if (webXmlDescriptor != null) { webArchive.setWebXML(new StringAsset(webXmlDescriptor.exportAsString())); From 48015e8cf7a01e490df40a1d4d7e269a17ad374d Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Mon, 8 Nov 2021 14:23:24 +0100 Subject: [PATCH 3/3] Initial TCK tests for build compatible extensions --- .../cdi/tck/shrinkwrap/ArchiveBuilder.java | 11 +++ .../ChangeBeanQualifierExtension.java | 34 ++++++++++ .../ChangeBeanQualifierTest.java | 29 ++++++++ .../changeBeanQualifier/MyOtherService.java | 10 +++ .../changeBeanQualifier/MyQualifier.java | 11 +++ .../changeBeanQualifier/MyService.java | 5 ++ .../changeBeanQualifier/MyServiceBar.java | 10 +++ .../changeBeanQualifier/MyServiceBaz.java | 8 +++ .../changeBeanQualifier/MyServiceFoo.java | 11 +++ .../ChangeInjectionPointExtension.java | 16 +++++ .../ChangeInjectionPointTest.java | 29 ++++++++ .../changeInjectionPoint/MyOtherService.java | 10 +++ .../changeInjectionPoint/MyQualifier.java | 11 +++ .../changeInjectionPoint/MyService.java | 5 ++ .../changeInjectionPoint/MyServiceBar.java | 12 ++++ .../changeInjectionPoint/MyServiceFoo.java | 11 +++ .../ChangeObserverQualifierExtension.java | 27 ++++++++ .../ChangeObserverQualifierTest.java | 52 ++++++++++++++ .../changeObserverQualifier/MyConsumer.java | 20 ++++++ .../changeObserverQualifier/MyEvent.java | 9 +++ .../changeObserverQualifier/MyProducer.java | 20 ++++++ .../changeObserverQualifier/MyQualifier.java | 11 +++ .../CustomInterceptorBindingExtension.java | 27 ++++++++ .../CustomInterceptorBindingTest.java | 27 ++++++++ .../MyCustomInterceptor.java | 14 ++++ .../MyCustomInterceptorBinding.java | 9 +++ .../customInterceptorBinding/MyService.java | 11 +++ .../CustomQualifierExtension.java | 21 ++++++ .../customQualifier/CustomQualifierTest.java | 28 ++++++++ .../customQualifier/MyCustomQualifier.java | 24 +++++++ .../extensions/customQualifier/MyService.java | 5 ++ .../customQualifier/MyServiceBar.java | 11 +++ .../customQualifier/MyServiceFoo.java | 7 ++ .../CustomStereotypeExtension.java | 18 +++++ .../CustomStereotypeTest.java | 31 +++++++++ .../customStereotype/MyCustomStereotype.java | 8 +++ .../customStereotype/MyService.java | 8 +++ .../priority/PriorityExtension.java | 67 +++++++++++++++++++ .../extensions/priority/PriorityTest.java | 25 +++++++ .../extensions/registration/MyQualifier.java | 11 +++ .../extensions/registration/MyService.java | 5 ++ .../extensions/registration/MyServiceBar.java | 9 +++ .../registration/MyServiceBarProducer.java | 14 ++++ .../extensions/registration/MyServiceFoo.java | 16 +++++ .../registration/RegistrationExtension.java | 48 +++++++++++++ .../registration/RegistrationTest.java | 25 +++++++ .../syntheticBean/MyComplexValue.java | 15 +++++ .../extensions/syntheticBean/MyEnum.java | 6 ++ .../extensions/syntheticBean/MyPojo.java | 11 +++ .../syntheticBean/MyPojoCreator.java | 21 ++++++ .../syntheticBean/MyPojoDisposer.java | 17 +++++ .../extensions/syntheticBean/MyQualifier.java | 11 +++ .../extensions/syntheticBean/MyService.java | 14 ++++ .../syntheticBean/MySimpleValue.java | 37 ++++++++++ .../syntheticBean/SyntheticBeanExtension.java | 41 ++++++++++++ .../syntheticBean/SyntheticBeanTest.java | 65 ++++++++++++++++++ .../MyApplicationScopedBean.java | 4 ++ .../MyApplicationScopedBeanCreator.java | 16 +++++ .../MyDependentBean.java | 4 ++ .../MyDependentBeanCreator.java | 16 +++++ .../MyDependentBeanDisposer.java | 15 +++++ .../SyntheticBeanInjectionPointExtension.java | 23 +++++++ .../SyntheticBeanInjectionPointTest.java | 59 ++++++++++++++++ .../MyDependentBean.java | 23 +++++++ .../syntheticBeanWithLookup/MyPojo.java | 20 ++++++ .../MyPojoCreator.java | 20 ++++++ .../MyPojoDisposer.java | 20 ++++++ .../SyntheticBeanWithLookupExtension.java | 24 +++++++ .../SyntheticBeanWithLookupTest.java | 56 ++++++++++++++++ .../extensions/syntheticObserver/MyEvent.java | 9 +++ .../syntheticObserver/MyObserver.java | 17 +++++ .../syntheticObserver/MyQualifier.java | 11 +++ .../syntheticObserver/MyService.java | 20 ++++++ .../SyntheticObserverExtension.java | 20 ++++++ .../SyntheticObserverTest.java | 38 +++++++++++ .../MyData.java | 9 +++ .../MyObserver.java | 21 ++++++ .../MyService.java | 18 +++++ ...cObserverOfParameterizedTypeExtension.java | 16 +++++ ...theticObserverOfParameterizedTypeTest.java | 33 +++++++++ .../validation/ValidationExtension.java | 12 ++++ .../extensions/validation/ValidationTest.java | 28 ++++++++ pom.xml | 2 +- 83 files changed, 1622 insertions(+), 1 deletion(-) create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/ChangeBeanQualifierExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/ChangeBeanQualifierTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyOtherService.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyQualifier.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyService.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyServiceBar.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyServiceBaz.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyServiceFoo.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/ChangeInjectionPointExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/ChangeInjectionPointTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyOtherService.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyQualifier.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyService.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyServiceBar.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyServiceFoo.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/ChangeObserverQualifierExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/ChangeObserverQualifierTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyConsumer.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyEvent.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyProducer.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyQualifier.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/CustomInterceptorBindingExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/CustomInterceptorBindingTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/MyCustomInterceptor.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/MyCustomInterceptorBinding.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/MyService.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/CustomQualifierExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/CustomQualifierTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyCustomQualifier.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyService.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyServiceBar.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyServiceFoo.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/CustomStereotypeExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/CustomStereotypeTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/MyCustomStereotype.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/MyService.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/priority/PriorityExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/priority/PriorityTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyQualifier.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyService.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyServiceBar.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyServiceBarProducer.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyServiceFoo.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/RegistrationExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/RegistrationTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyComplexValue.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyEnum.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyPojo.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyPojoCreator.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyPojoDisposer.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyQualifier.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyService.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MySimpleValue.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/SyntheticBeanExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/SyntheticBeanTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyApplicationScopedBean.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyApplicationScopedBeanCreator.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyDependentBean.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyDependentBeanCreator.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyDependentBeanDisposer.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/SyntheticBeanInjectionPointExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/SyntheticBeanInjectionPointTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyDependentBean.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyPojo.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyPojoCreator.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyPojoDisposer.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/SyntheticBeanWithLookupExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/SyntheticBeanWithLookupTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyEvent.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyObserver.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyQualifier.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyService.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/SyntheticObserverExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/SyntheticObserverTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/MyData.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/MyObserver.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/MyService.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/SyntheticObserverOfParameterizedTypeExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/SyntheticObserverOfParameterizedTypeTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/validation/ValidationExtension.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/validation/ValidationTest.java diff --git a/impl/src/main/java/org/jboss/cdi/tck/shrinkwrap/ArchiveBuilder.java b/impl/src/main/java/org/jboss/cdi/tck/shrinkwrap/ArchiveBuilder.java index 46c7c30229..94d4ca41d0 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/shrinkwrap/ArchiveBuilder.java +++ b/impl/src/main/java/org/jboss/cdi/tck/shrinkwrap/ArchiveBuilder.java @@ -16,6 +16,7 @@ */ package org.jboss.cdi.tck.shrinkwrap; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; import jakarta.enterprise.inject.spi.Extension; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.RunAsClient; @@ -224,6 +225,16 @@ public T withExtensions(Class... extensionClasses) { return withServiceProvider(new ServiceProviderDescriptor(Extension.class, extensionClasses)); } + /** + * Add CDI build compatible extension. This method does not add the specified extension class to the archive. + * + * @param extensionClass + * @return self + */ + public T withBuildCompatibleExtension(Class extensionClass) { + return withServiceProvider(new ServiceProviderDescriptor(BuildCompatibleExtension.class, extensionClass)); + } + /** * Add service provider. * diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/ChangeBeanQualifierExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/ChangeBeanQualifierExtension.java new file mode 100644 index 0000000000..3f5fb8130d --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/ChangeBeanQualifierExtension.java @@ -0,0 +1,34 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeBeanQualifier; + +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.ClassConfig; +import jakarta.enterprise.inject.build.compatible.spi.Discovery; +import jakarta.enterprise.inject.build.compatible.spi.Enhancement; +import jakarta.enterprise.inject.build.compatible.spi.FieldConfig; +import jakarta.enterprise.inject.build.compatible.spi.ScannedClasses; + +public class ChangeBeanQualifierExtension implements BuildCompatibleExtension { + @Discovery + public void discovery(ScannedClasses scan) { + scan.add(MyServiceFoo.class.getName()); + scan.add(MyServiceBar.class.getName()); + scan.add(MyServiceBaz.class.getName()); + } + + @Enhancement(types = MyServiceFoo.class) + public void foo(ClassConfig clazz) { + clazz.removeAnnotation(ann -> ann.name().equals(MyQualifier.class.getName())); + } + + @Enhancement(types = MyServiceBar.class) + public void bar(ClassConfig clazz) { + clazz.addAnnotation(MyQualifier.class); + } + + @Enhancement(types = MyOtherService.class) + public void service(FieldConfig field) { + if ("myService".equals(field.info().name())) { + field.addAnnotation(MyQualifier.class); + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/ChangeBeanQualifierTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/ChangeBeanQualifierTest.java new file mode 100644 index 0000000000..aa93905939 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/ChangeBeanQualifierTest.java @@ -0,0 +1,29 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeBeanQualifier; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; + +@SpecVersion(spec = "cdi", version = "4.0") +public class ChangeBeanQualifierTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(ChangeBeanQualifierTest.class) + .withBuildCompatibleExtension(ChangeBeanQualifierExtension.class) + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void test() { + MyOtherService bean = getContextualReference(MyOtherService.class); + // all beans are dependent, so there's no client proxy and direct field access and `instanceof` are OK + assertTrue(bean.myService instanceof MyServiceBar); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyOtherService.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyOtherService.java new file mode 100644 index 0000000000..85a2c3a519 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyOtherService.java @@ -0,0 +1,10 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeBeanQualifier; + +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; + +@Dependent +public class MyOtherService { + @Inject + MyService myService; +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyQualifier.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyQualifier.java new file mode 100644 index 0000000000..754db6ce02 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyQualifier.java @@ -0,0 +1,11 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeBeanQualifier; + +import jakarta.inject.Qualifier; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface MyQualifier { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyService.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyService.java new file mode 100644 index 0000000000..dd2444fe5f --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyService.java @@ -0,0 +1,5 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeBeanQualifier; + +public interface MyService { + String hello(); +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyServiceBar.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyServiceBar.java new file mode 100644 index 0000000000..23a385d806 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyServiceBar.java @@ -0,0 +1,10 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeBeanQualifier; + +public class MyServiceBar implements MyService { + private static final String VALUE = "bar"; + + @Override + public String hello() { + return VALUE; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyServiceBaz.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyServiceBaz.java new file mode 100644 index 0000000000..27f0f95f13 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyServiceBaz.java @@ -0,0 +1,8 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeBeanQualifier; + +public class MyServiceBaz implements MyService { + @Override + public String hello() { + throw new UnsupportedOperationException(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyServiceFoo.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyServiceFoo.java new file mode 100644 index 0000000000..cee7e63aa9 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeBeanQualifier/MyServiceFoo.java @@ -0,0 +1,11 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeBeanQualifier; + +@MyQualifier +public class MyServiceFoo implements MyService { + private final String value = "foo"; + + @Override + public String hello() { + return value; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/ChangeInjectionPointExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/ChangeInjectionPointExtension.java new file mode 100644 index 0000000000..7f17c93b7a --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/ChangeInjectionPointExtension.java @@ -0,0 +1,16 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeInjectionPoint; + +import jakarta.enterprise.inject.build.compatible.spi.AnnotationBuilder; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.ClassConfig; +import jakarta.enterprise.inject.build.compatible.spi.Enhancement; + +public class ChangeInjectionPointExtension implements BuildCompatibleExtension { + @Enhancement(types = MyOtherService.class) + public void service(ClassConfig clazz) { + clazz.fields() + .stream() + .filter(it -> "myService".equals(it.info().name())) + .forEach(field -> field.addAnnotation(AnnotationBuilder.of(MyQualifier.class).build())); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/ChangeInjectionPointTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/ChangeInjectionPointTest.java new file mode 100644 index 0000000000..4a95a6e1fa --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/ChangeInjectionPointTest.java @@ -0,0 +1,29 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeInjectionPoint; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; + +@SpecVersion(spec = "cdi", version = "4.0") +public class ChangeInjectionPointTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(ChangeInjectionPointTest.class) + .withBuildCompatibleExtension(ChangeInjectionPointExtension.class) + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void test() { + MyOtherService bean = getContextualReference(MyOtherService.class); + // all beans are dependent, so there's no client proxy and direct field access and `instanceof` are OK + assertTrue(bean.myService instanceof MyServiceBar); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyOtherService.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyOtherService.java new file mode 100644 index 0000000000..6aa49d5196 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyOtherService.java @@ -0,0 +1,10 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeInjectionPoint; + +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; + +@Dependent +public class MyOtherService { + @Inject + MyService myService; +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyQualifier.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyQualifier.java new file mode 100644 index 0000000000..96887561a6 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyQualifier.java @@ -0,0 +1,11 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeInjectionPoint; + +import jakarta.inject.Qualifier; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface MyQualifier { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyService.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyService.java new file mode 100644 index 0000000000..9e124cbec8 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyService.java @@ -0,0 +1,5 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeInjectionPoint; + +public interface MyService { + String hello(); +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyServiceBar.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyServiceBar.java new file mode 100644 index 0000000000..77d251cd00 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyServiceBar.java @@ -0,0 +1,12 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeInjectionPoint; + +import jakarta.enterprise.context.Dependent; + +@Dependent +@MyQualifier +public class MyServiceBar implements MyService { + @Override + public String hello() { + return "bar"; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyServiceFoo.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyServiceFoo.java new file mode 100644 index 0000000000..a59c0aed96 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeInjectionPoint/MyServiceFoo.java @@ -0,0 +1,11 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeInjectionPoint; + +import jakarta.enterprise.context.Dependent; + +@Dependent +public class MyServiceFoo implements MyService { + @Override + public String hello() { + return "foo"; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/ChangeObserverQualifierExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/ChangeObserverQualifierExtension.java new file mode 100644 index 0000000000..b25bb4d601 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/ChangeObserverQualifierExtension.java @@ -0,0 +1,27 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeObserverQualifier; + +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Discovery; +import jakarta.enterprise.inject.build.compatible.spi.Enhancement; +import jakarta.enterprise.inject.build.compatible.spi.MethodConfig; +import jakarta.enterprise.inject.build.compatible.spi.ScannedClasses; + +public class ChangeObserverQualifierExtension implements BuildCompatibleExtension { + @Discovery + public void discovery(ScannedClasses scan) { + scan.add(MyConsumer.class.getName()); + scan.add(MyProducer.class.getName()); + } + + @Enhancement(types = MyConsumer.class) + public void consumer(MethodConfig method) { + switch (method.info().name()) { + case "consume": + method.parameters().get(0).addAnnotation(MyQualifier.class); + break; + case "noConsume": + method.parameters().get(0).removeAllAnnotations(); + break; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/ChangeObserverQualifierTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/ChangeObserverQualifierTest.java new file mode 100644 index 0000000000..18eaba0743 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/ChangeObserverQualifierTest.java @@ -0,0 +1,52 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeObserverQualifier; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.spi.Bean; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +@SpecVersion(spec = "cdi", version = "4.0") +public class ChangeObserverQualifierTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + // no beans.xml + an extension = not a bean archive, bean classes are added through the extension + return new WebArchiveBuilder() + .withTestClassPackage(ChangeObserverQualifierTest.class) + .withBuildCompatibleExtension(ChangeObserverQualifierExtension.class) + .withoutBeansXml() + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void test() { + MyProducer producer = getContextualReference(MyProducer.class); + producer.produce(); + + assertEquals(MyConsumer.events, Set.of("qualified")); + } + + @Test + public void testScopeIsRetained() { + { + Set> beans = getBeans(MyProducer.class); + assertEquals(beans.size(), 1); + assertEquals(ApplicationScoped.class, beans.iterator().next().getScope()); + } + + { + Set> beans = getBeans(MyConsumer.class); + assertEquals(beans.size(), 1); + assertEquals(ApplicationScoped.class, beans.iterator().next().getScope()); + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyConsumer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyConsumer.java new file mode 100644 index 0000000000..0bb1a42182 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyConsumer.java @@ -0,0 +1,20 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeObserverQualifier; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Observes; + +import java.util.HashSet; +import java.util.Set; + +@ApplicationScoped +public class MyConsumer { + static final Set events = new HashSet<>(); + + void consume(@Observes MyEvent event) { + events.add(event.payload); + } + + void noConsume(@Observes MyEvent event) { + events.add("must-not-happen-" + event.payload); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyEvent.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyEvent.java new file mode 100644 index 0000000000..53ab60b258 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyEvent.java @@ -0,0 +1,9 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeObserverQualifier; + +public class MyEvent { + final String payload; + + public MyEvent(String payload) { + this.payload = payload; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyProducer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyProducer.java new file mode 100644 index 0000000000..965a04166d --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyProducer.java @@ -0,0 +1,20 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeObserverQualifier; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Event; +import jakarta.inject.Inject; + +@ApplicationScoped +public class MyProducer { + @Inject + Event unqualified; + + @Inject + @MyQualifier + Event qualified; + + void produce() { + unqualified.fire(new MyEvent("unqualified")); + qualified.fire(new MyEvent("qualified")); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyQualifier.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyQualifier.java new file mode 100644 index 0000000000..4581ebfc31 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/MyQualifier.java @@ -0,0 +1,11 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.changeObserverQualifier; + +import jakarta.inject.Qualifier; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface MyQualifier { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/CustomInterceptorBindingExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/CustomInterceptorBindingExtension.java new file mode 100644 index 0000000000..c70e15f115 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/CustomInterceptorBindingExtension.java @@ -0,0 +1,27 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customInterceptorBinding; + +import jakarta.annotation.Priority; +import jakarta.enterprise.inject.build.compatible.spi.AnnotationBuilder; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.ClassConfig; +import jakarta.enterprise.inject.build.compatible.spi.Discovery; +import jakarta.enterprise.inject.build.compatible.spi.Enhancement; +import jakarta.enterprise.inject.build.compatible.spi.MetaAnnotations; +import jakarta.enterprise.inject.build.compatible.spi.ScannedClasses; +import jakarta.enterprise.util.Nonbinding; + +public class CustomInterceptorBindingExtension implements BuildCompatibleExtension { + @Discovery + public void discovery(MetaAnnotations meta) { + ClassConfig cfg = meta.addInterceptorBinding(MyCustomInterceptorBinding.class); + cfg.methods() + .stream() + .filter(it -> "value".equals(it.info().name())) + .forEach(it -> it.addAnnotation(Nonbinding.class)); + } + + @Enhancement(types = MyCustomInterceptor.class) + public void interceptorPriority(ClassConfig clazz) { + clazz.addAnnotation(AnnotationBuilder.of(Priority.class).value(1).build()); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/CustomInterceptorBindingTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/CustomInterceptorBindingTest.java new file mode 100644 index 0000000000..20067dbc42 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/CustomInterceptorBindingTest.java @@ -0,0 +1,27 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customInterceptorBinding; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.0") +public class CustomInterceptorBindingTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(CustomInterceptorBindingTest.class) + .withBuildCompatibleExtension(CustomInterceptorBindingExtension.class) + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void test() { + assertEquals("Intercepted: Hello!", getContextualReference(MyService.class).hello()); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/MyCustomInterceptor.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/MyCustomInterceptor.java new file mode 100644 index 0000000000..7d7bf6023a --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/MyCustomInterceptor.java @@ -0,0 +1,14 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customInterceptorBinding; + +import jakarta.interceptor.AroundInvoke; +import jakarta.interceptor.Interceptor; +import jakarta.interceptor.InvocationContext; + +@Interceptor +@MyCustomInterceptorBinding("something") +public class MyCustomInterceptor { + @AroundInvoke + public Object intercept(InvocationContext ctx) throws Exception { + return "Intercepted: " + ctx.proceed(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/MyCustomInterceptorBinding.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/MyCustomInterceptorBinding.java new file mode 100644 index 0000000000..273b25cd8d --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/MyCustomInterceptorBinding.java @@ -0,0 +1,9 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customInterceptorBinding; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface MyCustomInterceptorBinding { + String value(); +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/MyService.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/MyService.java new file mode 100644 index 0000000000..2f9abf063a --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customInterceptorBinding/MyService.java @@ -0,0 +1,11 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customInterceptorBinding; + +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +@MyCustomInterceptorBinding("this should be ignored, the value member should be treated as @Nonbinding") +public class MyService { + public String hello() { + return "Hello!"; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/CustomQualifierExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/CustomQualifierExtension.java new file mode 100644 index 0000000000..ef7d0c2947 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/CustomQualifierExtension.java @@ -0,0 +1,21 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customQualifier; + +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.ClassConfig; +import jakarta.enterprise.inject.build.compatible.spi.Discovery; +import jakarta.enterprise.inject.build.compatible.spi.MetaAnnotations; +import jakarta.enterprise.inject.build.compatible.spi.ScannedClasses; +import jakarta.enterprise.util.Nonbinding; + +public class CustomQualifierExtension implements BuildCompatibleExtension { + @Discovery + public void discovery(MetaAnnotations meta, ScannedClasses scan) { + scan.add(MyServiceFoo.class.getName()); + + ClassConfig cfg = meta.addQualifier(MyCustomQualifier.class); + cfg.methods() + .stream() + .filter(it -> "value".equals(it.info().name())) + .forEach(it -> it.addAnnotation(Nonbinding.class)); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/CustomQualifierTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/CustomQualifierTest.java new file mode 100644 index 0000000000..4ba08f548c --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/CustomQualifierTest.java @@ -0,0 +1,28 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customQualifier; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.0") +public class CustomQualifierTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(CustomQualifierTest.class) + .withBuildCompatibleExtension(CustomQualifierExtension.class) + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void test() { + assertEquals("bar", getContextualReference(MyService.class, + new MyCustomQualifier.Literal("something")).hello()); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyCustomQualifier.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyCustomQualifier.java new file mode 100644 index 0000000000..88f1861c13 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyCustomQualifier.java @@ -0,0 +1,24 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customQualifier; + +import jakarta.enterprise.util.AnnotationLiteral; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface MyCustomQualifier { + String value(); + + class Literal extends AnnotationLiteral implements MyCustomQualifier { + private final String value; + + Literal(String value) { + this.value = value; + } + + @Override + public String value() { + return value; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyService.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyService.java new file mode 100644 index 0000000000..b6374ec549 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyService.java @@ -0,0 +1,5 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customQualifier; + +public interface MyService { + String hello(); +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyServiceBar.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyServiceBar.java new file mode 100644 index 0000000000..61d08d2764 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyServiceBar.java @@ -0,0 +1,11 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customQualifier; + +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +@MyCustomQualifier("this should be ignored, the value member should be treated as @Nonbinding") +public class MyServiceBar implements MyService { + public String hello() { + return "bar"; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyServiceFoo.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyServiceFoo.java new file mode 100644 index 0000000000..914a9bb97f --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customQualifier/MyServiceFoo.java @@ -0,0 +1,7 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customQualifier; + +public class MyServiceFoo implements MyService { + public String hello() { + return "foo"; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/CustomStereotypeExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/CustomStereotypeExtension.java new file mode 100644 index 0000000000..5e1f6a54a0 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/CustomStereotypeExtension.java @@ -0,0 +1,18 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customStereotype; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.ClassConfig; +import jakarta.enterprise.inject.build.compatible.spi.Discovery; +import jakarta.enterprise.inject.build.compatible.spi.MetaAnnotations; +import jakarta.enterprise.inject.build.compatible.spi.ScannedClasses; + +public class CustomStereotypeExtension implements BuildCompatibleExtension { + @Discovery + public void discovery(MetaAnnotations meta, ScannedClasses scan) { + scan.add(MyService.class.getName()); + + ClassConfig cfg = meta.addStereotype(MyCustomStereotype.class); + cfg.addAnnotation(ApplicationScoped.class); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/CustomStereotypeTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/CustomStereotypeTest.java new file mode 100644 index 0000000000..a2133ca468 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/CustomStereotypeTest.java @@ -0,0 +1,31 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customStereotype; + +import jakarta.enterprise.context.ApplicationScoped; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.0") +public class CustomStereotypeTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + // no beans.xml + an extension = not a bean archive, bean classes are added through the extension + return new WebArchiveBuilder() + .withTestClassPackage(CustomStereotypeTest.class) + .withBuildCompatibleExtension(CustomStereotypeExtension.class) + .withoutBeansXml() + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void test() { + assertEquals(ApplicationScoped.class, getUniqueBean(MyService.class).getScope()); + assertEquals("Hello!", getContextualReference(MyService.class).hello()); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/MyCustomStereotype.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/MyCustomStereotype.java new file mode 100644 index 0000000000..8d333881f7 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/MyCustomStereotype.java @@ -0,0 +1,8 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customStereotype; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface MyCustomStereotype { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/MyService.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/MyService.java new file mode 100644 index 0000000000..41f8bcfd97 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/MyService.java @@ -0,0 +1,8 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.customStereotype; + +@MyCustomStereotype +public class MyService { + public String hello() { + return "Hello!"; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/priority/PriorityExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/priority/PriorityExtension.java new file mode 100644 index 0000000000..5132527304 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/priority/PriorityExtension.java @@ -0,0 +1,67 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.priority; + +import jakarta.annotation.Priority; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.ClassConfig; +import jakarta.enterprise.inject.build.compatible.spi.Discovery; +import jakarta.enterprise.inject.build.compatible.spi.Enhancement; +import jakarta.enterprise.inject.build.compatible.spi.Messages; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Validation; + +import java.util.LinkedHashSet; +import java.util.List; + +public class PriorityExtension implements BuildCompatibleExtension { + private final LinkedHashSet invocations = new LinkedHashSet<>(); + + @Discovery + @Priority(10) + public void first() { + invocations.add("1"); + } + + @Discovery + @Priority(20) + public void second() { + invocations.add("2"); + } + + @Enhancement(types = Object.class, withSubtypes = true) + @Priority(15) + public void third(ClassConfig clazz) { + invocations.add("3"); + } + + @Registration(types = Object.class) + @Priority(5) + public void fourth(BeanInfo clazz) { + invocations.add("4"); + } + + @Validation + @Priority(1_000) + public void fifth() { + invocations.add("5"); + } + + @Validation + public void sixth() { + invocations.add("6"); + } + + @Validation + @Priority(10_000) + public void seventh() { + invocations.add("7"); + } + + @Validation + @Priority(1_000_000) + public void test(Messages msg) { + if (!List.of("1", "2", "3", "4", "5", "6", "7").equals(List.copyOf(invocations))) { + msg.error("Incorrect invocation order of extension methods"); + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/priority/PriorityTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/priority/PriorityTest.java new file mode 100644 index 0000000000..5c234a643c --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/priority/PriorityTest.java @@ -0,0 +1,25 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.priority; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "4.0") +public class PriorityTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(PriorityTest.class) + .withBuildCompatibleExtension(PriorityExtension.class) + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void trigger() { + // test is present in PriorityExtension and if it fails, deployment should fail + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyQualifier.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyQualifier.java new file mode 100644 index 0000000000..56097bd9be --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyQualifier.java @@ -0,0 +1,11 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.registration; + +import jakarta.inject.Qualifier; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface MyQualifier { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyService.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyService.java new file mode 100644 index 0000000000..246dc79b84 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyService.java @@ -0,0 +1,5 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.registration; + +public interface MyService { + String hello(); +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyServiceBar.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyServiceBar.java new file mode 100644 index 0000000000..985a94a75c --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyServiceBar.java @@ -0,0 +1,9 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.registration; + +// intentionally not a bean, to test that producer-based bean is processed +public class MyServiceBar implements MyService { + @Override + public String hello() { + return "bar"; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyServiceBarProducer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyServiceBarProducer.java new file mode 100644 index 0000000000..c94d08caa2 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyServiceBarProducer.java @@ -0,0 +1,14 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.registration; + +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Produces; + +@Dependent +public class MyServiceBarProducer { + @Produces + @Dependent + @MyQualifier + public MyServiceBar produce() { + return new MyServiceBar(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyServiceFoo.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyServiceFoo.java new file mode 100644 index 0000000000..bf8f235004 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/MyServiceFoo.java @@ -0,0 +1,16 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.registration; + +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.event.Startup; + +@Dependent +public class MyServiceFoo implements MyService { + @Override + public String hello() { + return "foo"; + } + + void init(@Observes Startup event) { + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/RegistrationExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/RegistrationExtension.java new file mode 100644 index 0000000000..761a20471d --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/RegistrationExtension.java @@ -0,0 +1,48 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.registration; + +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Messages; +import jakarta.enterprise.inject.build.compatible.spi.ObserverInfo; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Types; +import jakarta.enterprise.inject.build.compatible.spi.Validation; + +import java.util.concurrent.atomic.AtomicInteger; + +public class RegistrationExtension implements BuildCompatibleExtension { + private final AtomicInteger beanCounter = new AtomicInteger(); + private final AtomicInteger beanMyQualifierCounter = new AtomicInteger(); + private final AtomicInteger observerCounter = new AtomicInteger(); + + @Registration(types = MyService.class) + public void beans(BeanInfo bean) { + beanCounter.incrementAndGet(); + + if (bean.qualifiers().stream().anyMatch(it -> it.name().equals(MyQualifier.class.getName()))) { + beanMyQualifierCounter.incrementAndGet(); + } + } + + @Registration(types = Object.class) + public void observers(ObserverInfo observer, Types types) { + if (observer.declaringClass().superInterfaces().contains(types.of(MyService.class))) { + observerCounter.incrementAndGet(); + } + } + + @Validation + public void test(Messages msg) { + if (beanCounter.get() != 2) { + msg.error("Should see 2 beans of type MyService"); + } + + if (beanMyQualifierCounter.get() != 1) { + msg.error("Should see 1 bean of type MyService with qualifier MyQualifier"); + } + + if (observerCounter.get() != 1) { + msg.error("Should see 1 observer declared in class that implements MyService"); + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/RegistrationTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/RegistrationTest.java new file mode 100644 index 0000000000..545d867a1f --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/registration/RegistrationTest.java @@ -0,0 +1,25 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.registration; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "4.0") +public class RegistrationTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(RegistrationTest.class) + .withBuildCompatibleExtension(RegistrationExtension.class) + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void trigger() { + // test is present in RegistrationExtension and if it fails, deployment should fail + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyComplexValue.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyComplexValue.java new file mode 100644 index 0000000000..a86a4120fc --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyComplexValue.java @@ -0,0 +1,15 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBean; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface MyComplexValue { + int number(); + + MyEnum enumeration(); + + Class type(); + + MySimpleValue nested(); +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyEnum.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyEnum.java new file mode 100644 index 0000000000..7916f744c1 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyEnum.java @@ -0,0 +1,6 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBean; + +public enum MyEnum { + YES, + NO, +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyPojo.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyPojo.java new file mode 100644 index 0000000000..098cdc4641 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyPojo.java @@ -0,0 +1,11 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBean; + +public class MyPojo { + final String text; + final MyComplexValue ann; + + MyPojo(String text, MyComplexValue ann) { + this.text = text; + this.ann = ann; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyPojoCreator.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyPojoCreator.java new file mode 100644 index 0000000000..c947a77065 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyPojoCreator.java @@ -0,0 +1,21 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBean; + +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanCreator; +import jakarta.enterprise.inject.spi.InjectionPoint; + +public class MyPojoCreator implements SyntheticBeanCreator { + @Override + public MyPojo create(Instance lookup, Parameters params) { + String name = params.get("name", String.class); + MyComplexValue ann = params.get("data", MyComplexValue.class); + + InjectionPoint injectionPoint = lookup.select(InjectionPoint.class).get(); + if (injectionPoint.getQualifiers().stream().anyMatch(it -> it.annotationType().equals(MyQualifier.class))) { + return new MyPojo("Hello @MyQualifier " + name, ann); + } + + return new MyPojo("Hello " + name, ann); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyPojoDisposer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyPojoDisposer.java new file mode 100644 index 0000000000..7c96d79198 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyPojoDisposer.java @@ -0,0 +1,17 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBean; + +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanDisposer; + +import java.util.HashSet; +import java.util.Set; + +public class MyPojoDisposer implements SyntheticBeanDisposer { + static final Set disposed = new HashSet<>(); + + @Override + public void dispose(MyPojo instance, Instance lookup, Parameters params) { + disposed.add(instance.text); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyQualifier.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyQualifier.java new file mode 100644 index 0000000000..e37cfb8f1c --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyQualifier.java @@ -0,0 +1,11 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBean; + +import jakarta.inject.Qualifier; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface MyQualifier { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyService.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyService.java new file mode 100644 index 0000000000..b95c48aa9f --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MyService.java @@ -0,0 +1,14 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBean; + +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; + +@Dependent +public class MyService { + @Inject + MyPojo unqualified; + + @Inject + @MyQualifier + MyPojo qualified; +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MySimpleValue.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MySimpleValue.java new file mode 100644 index 0000000000..36c6e90328 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/MySimpleValue.java @@ -0,0 +1,37 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBean; + +import jakarta.enterprise.util.AnnotationLiteral; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface MySimpleValue { + String value(); + + byte[] bytes() default { 1, 2, 3 }; + + class Literal extends AnnotationLiteral implements MySimpleValue { + private final String value; + private final byte[] bytes; + + Literal(String value) { + this(value, new byte[] { 1, 2, 3 }); + } + + Literal(String value, byte[] bytes) { + this.value = value; + this.bytes = bytes; + } + + @Override + public String value() { + return value; + } + + @Override + public byte[] bytes() { + return bytes; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/SyntheticBeanExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/SyntheticBeanExtension.java new file mode 100644 index 0000000000..f442c09857 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/SyntheticBeanExtension.java @@ -0,0 +1,41 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBean; + +import jakarta.enterprise.inject.build.compatible.spi.AnnotationBuilder; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.inject.build.compatible.spi.Types; + +public class SyntheticBeanExtension implements BuildCompatibleExtension { + @Synthesis + public void synthesize(SyntheticComponents syn, Types types) { + syn.addBean(MyPojo.class) + .type(MyPojo.class) + .withParam("name", "World") + .withParam("data", AnnotationBuilder.of(MyComplexValue.class) + .member("number", 42) + .member("enumeration", MyEnum.YES) + .member("type", MyEnum.class) + .member("nested", new MySimpleValue.Literal("yes", new byte[] { 4, 5, 6 })) + .build()) + .createWith(MyPojoCreator.class) + .disposeWith(MyPojoDisposer.class); + + syn.addBean(MyPojo.class) + .type(MyPojo.class) + .qualifier(MyQualifier.class) + .withParam("name", "Special") + .withParam("data", AnnotationBuilder.of(MyComplexValue.class) + .member("number", 13) + .member("enumeration", MyEnum.class, "NO") + .member("type", types.ofClass("org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBean.MyEnum") + .declaration()) + .member("nested", AnnotationBuilder.of( + types.ofClass("org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBean.MySimpleValue") + .declaration()) + .value("no").build()) + .build()) + .createWith(MyPojoCreator.class) + .disposeWith(MyPojoDisposer.class); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/SyntheticBeanTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/SyntheticBeanTest.java new file mode 100644 index 0000000000..b0649fa4a7 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBean/SyntheticBeanTest.java @@ -0,0 +1,65 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBean; + +import jakarta.enterprise.inject.Instance; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +@SpecVersion(spec = "cdi", version = "4.0") +public class SyntheticBeanTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(SyntheticBeanTest.class) + .withBuildCompatibleExtension(SyntheticBeanExtension.class) + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void test() { + Instance lookup = getCurrentBeanContainer().createInstance(); + + Instance.Handle handle = lookup.select(MyService.class).getHandle(); + MyService myService = handle.get(); + + { + assertEquals("Hello World", myService.unqualified.text); + + MyComplexValue ann = myService.unqualified.ann; + assertNotNull(ann); + assertEquals(42, ann.number()); + assertEquals(MyEnum.YES, ann.enumeration()); + assertEquals(MyEnum.class, ann.type()); + assertEquals("yes", ann.nested().value()); + assertEquals(new byte[] { 4, 5, 6 }, ann.nested().bytes()); + } + + { + assertEquals("Hello @MyQualifier Special", myService.qualified.text); + + MyComplexValue ann = myService.qualified.ann; + assertNotNull(ann); + assertEquals(13, ann.number()); + assertEquals(MyEnum.NO, ann.enumeration()); + assertEquals(MyEnum.class, ann.type()); + assertEquals("no", ann.nested().value()); + assertEquals(new byte[] { 1, 2, 3 }, ann.nested().bytes()); + } + + assertEquals(0, MyPojoDisposer.disposed.size()); + + handle.destroy(); + + assertEquals(2, MyPojoDisposer.disposed.size()); + assertTrue(MyPojoDisposer.disposed.contains("Hello World")); + assertTrue(MyPojoDisposer.disposed.contains("Hello @MyQualifier Special")); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyApplicationScopedBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyApplicationScopedBean.java new file mode 100644 index 0000000000..bf1a7619ff --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyApplicationScopedBean.java @@ -0,0 +1,4 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanInjectionPoint; + +public class MyApplicationScopedBean { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyApplicationScopedBeanCreator.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyApplicationScopedBeanCreator.java new file mode 100644 index 0000000000..f2256b5aae --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyApplicationScopedBeanCreator.java @@ -0,0 +1,16 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanInjectionPoint; + +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanCreator; +import jakarta.enterprise.inject.spi.InjectionPoint; + +public class MyApplicationScopedBeanCreator implements SyntheticBeanCreator { + static InjectionPoint lookedUp = null; + + @Override + public MyApplicationScopedBean create(Instance lookup, Parameters params) { + lookedUp = lookup.select(InjectionPoint.class).get(); + return new MyApplicationScopedBean(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyDependentBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyDependentBean.java new file mode 100644 index 0000000000..181f4f906d --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyDependentBean.java @@ -0,0 +1,4 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanInjectionPoint; + +public class MyDependentBean { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyDependentBeanCreator.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyDependentBeanCreator.java new file mode 100644 index 0000000000..80f63d3aa5 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyDependentBeanCreator.java @@ -0,0 +1,16 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanInjectionPoint; + +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanCreator; +import jakarta.enterprise.inject.spi.InjectionPoint; + +public class MyDependentBeanCreator implements SyntheticBeanCreator { + static InjectionPoint lookedUp = null; + + @Override + public MyDependentBean create(Instance lookup, Parameters params) { + lookedUp = lookup.select(InjectionPoint.class).get(); + return new MyDependentBean(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyDependentBeanDisposer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyDependentBeanDisposer.java new file mode 100644 index 0000000000..3349e10a7c --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/MyDependentBeanDisposer.java @@ -0,0 +1,15 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanInjectionPoint; + +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanDisposer; +import jakarta.enterprise.inject.spi.InjectionPoint; + +public class MyDependentBeanDisposer implements SyntheticBeanDisposer { + static InjectionPoint lookedUp = null; + + @Override + public void dispose(MyDependentBean instance, Instance lookup, Parameters params) { + lookedUp = lookup.select(InjectionPoint.class).get(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/SyntheticBeanInjectionPointExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/SyntheticBeanInjectionPointExtension.java new file mode 100644 index 0000000000..ca556342e1 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/SyntheticBeanInjectionPointExtension.java @@ -0,0 +1,23 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanInjectionPoint; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; + +public class SyntheticBeanInjectionPointExtension implements BuildCompatibleExtension { + @Synthesis + public void synthesize(SyntheticComponents syn) { + syn.addBean(MyDependentBean.class) + .type(MyDependentBean.class) + .scope(Dependent.class) + .createWith(MyDependentBeanCreator.class) + .disposeWith(MyDependentBeanDisposer.class); + + syn.addBean(MyApplicationScopedBean.class) + .type(MyApplicationScopedBean.class) + .scope(ApplicationScoped.class) + .createWith(MyApplicationScopedBeanCreator.class); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/SyntheticBeanInjectionPointTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/SyntheticBeanInjectionPointTest.java new file mode 100644 index 0000000000..be761b1f5b --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanInjectionPoint/SyntheticBeanInjectionPointTest.java @@ -0,0 +1,59 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanInjectionPoint; + +import jakarta.enterprise.inject.Instance; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.fail; + +@SpecVersion(spec = "cdi", version = "4.0") +public class SyntheticBeanInjectionPointTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(SyntheticBeanInjectionPointTest.class) + .withBuildCompatibleExtension(SyntheticBeanInjectionPointExtension.class) + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void test() { + Instance lookup = getCurrentBeanContainer().createInstance(); + + // For historical reasons, the spec is a little loose on what should happen + // when looking up an `InjectionPoint` in a synthetic bean creation function + // of a non-`@Dependent` bean, or in a synthetic bean destruction function. + // Realistically, 2 different things may happen: the implementation returns + // `null`, or it throws an exception. Further, that exception may be swallowed + // by the `Instance.Handle#get` or `destroy` method. The only thing we can + // possibly test for is whether storing the `InjectionPoint` lookup result + // into a `static` field, whose previous value was `null`, changed that value. + + Instance.Handle handle = lookup.select(MyDependentBean.class).getHandle(); + try { + handle.get(); + } catch (Exception e) { + fail(); + } + assertNotNull(MyDependentBeanCreator.lookedUp); + + try { + handle.destroy(); + } catch (Exception ignored) { + } + assertNull(MyDependentBeanDisposer.lookedUp); + + try { + lookup.select(MyApplicationScopedBean.class).get(); + } catch (Exception ignored) { + } + assertNull(MyApplicationScopedBeanCreator.lookedUp); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyDependentBean.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyDependentBean.java new file mode 100644 index 0000000000..adf8e29bb4 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyDependentBean.java @@ -0,0 +1,23 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanWithLookup; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.Dependent; + +import java.util.concurrent.atomic.AtomicInteger; + +@Dependent +public class MyDependentBean { + static final AtomicInteger createdCounter = new AtomicInteger(0); + static final AtomicInteger destroyedCounter = new AtomicInteger(0); + + @PostConstruct + void postConstruct() { + createdCounter.incrementAndGet(); + } + + @PreDestroy + void preDestroy() { + destroyedCounter.incrementAndGet(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyPojo.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyPojo.java new file mode 100644 index 0000000000..170c37a17f --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyPojo.java @@ -0,0 +1,20 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanWithLookup; + +import java.util.concurrent.atomic.AtomicInteger; + +public class MyPojo { + static final AtomicInteger createdCounter = new AtomicInteger(0); + static final AtomicInteger destroyedCounter = new AtomicInteger(0); + + public MyPojo() { + createdCounter.incrementAndGet(); + } + + public String hello() { + return "Hello!"; + } + + public void destroy() { + destroyedCounter.incrementAndGet(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyPojoCreator.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyPojoCreator.java new file mode 100644 index 0000000000..b4adcd353e --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyPojoCreator.java @@ -0,0 +1,20 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanWithLookup; + +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanCreator; + +import java.util.concurrent.atomic.AtomicInteger; + +public class MyPojoCreator implements SyntheticBeanCreator { + static final AtomicInteger counter = new AtomicInteger(); + + @Override + public MyPojo create(Instance lookup, Parameters params) { + counter.incrementAndGet(); + + lookup.select(MyDependentBean.class).get(); + + return new MyPojo(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyPojoDisposer.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyPojoDisposer.java new file mode 100644 index 0000000000..9a47217ebf --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/MyPojoDisposer.java @@ -0,0 +1,20 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanWithLookup; + +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanDisposer; + +import java.util.concurrent.atomic.AtomicInteger; + +public class MyPojoDisposer implements SyntheticBeanDisposer { + static final AtomicInteger counter = new AtomicInteger(); + + @Override + public void dispose(MyPojo instance, Instance lookup, Parameters params) { + counter.incrementAndGet(); + + lookup.select(MyDependentBean.class).get(); + + instance.destroy(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/SyntheticBeanWithLookupExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/SyntheticBeanWithLookupExtension.java new file mode 100644 index 0000000000..94e00f658d --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/SyntheticBeanWithLookupExtension.java @@ -0,0 +1,24 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanWithLookup; + +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Discovery; +import jakarta.enterprise.inject.build.compatible.spi.ScannedClasses; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; + +public class SyntheticBeanWithLookupExtension implements BuildCompatibleExtension { + @Discovery + public void discovery(ScannedClasses scan) { + scan.add(MyDependentBean.class.getName()); + } + + @Synthesis + public void synthesise(SyntheticComponents syn) { + syn.addBean(MyPojo.class) + .type(MyPojo.class) + .scope(Dependent.class) + .createWith(MyPojoCreator.class) + .disposeWith(MyPojoDisposer.class); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/SyntheticBeanWithLookupTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/SyntheticBeanWithLookupTest.java new file mode 100644 index 0000000000..a50cf329a6 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/SyntheticBeanWithLookupTest.java @@ -0,0 +1,56 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticBeanWithLookup; + +import jakarta.enterprise.inject.Instance; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.0") +public class SyntheticBeanWithLookupTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + // no beans.xml + an extension = not a bean archive, bean classes are added through the extension + return new WebArchiveBuilder() + .withTestClassPackage(SyntheticBeanWithLookupTest.class) + .withBuildCompatibleExtension(SyntheticBeanWithLookupExtension.class) + .withoutBeansXml() + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void test() { + Instance lookup = getCurrentBeanContainer().createInstance(); + + assertEquals(0, MyPojo.createdCounter.get()); + assertEquals(0, MyPojo.destroyedCounter.get()); + assertEquals(0, MyPojoCreator.counter.get()); + assertEquals(0, MyPojoDisposer.counter.get()); + assertEquals(0, MyDependentBean.createdCounter.get()); + assertEquals(0, MyDependentBean.destroyedCounter.get()); + + Instance.Handle bean = lookup.select(MyPojo.class).getHandle(); + assertEquals("Hello!", bean.get().hello()); + + assertEquals(1, MyPojo.createdCounter.get()); + assertEquals(0, MyPojo.destroyedCounter.get()); + assertEquals(1, MyPojoCreator.counter.get()); + assertEquals(0, MyPojoDisposer.counter.get()); + assertEquals(1, MyDependentBean.createdCounter.get()); + assertEquals(0, MyDependentBean.destroyedCounter.get()); + + bean.destroy(); + + assertEquals(1, MyPojo.createdCounter.get()); + assertEquals(1, MyPojo.destroyedCounter.get()); + assertEquals(1, MyPojoCreator.counter.get()); + assertEquals(1, MyPojoDisposer.counter.get()); + assertEquals(2, MyDependentBean.createdCounter.get()); + assertEquals(2, MyDependentBean.destroyedCounter.get()); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyEvent.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyEvent.java new file mode 100644 index 0000000000..e470a6a929 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyEvent.java @@ -0,0 +1,9 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticObserver; + +public class MyEvent { + final String payload; + + MyEvent(String payload) { + this.payload = payload; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyObserver.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyObserver.java new file mode 100644 index 0000000000..dd8b5f4742 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyObserver.java @@ -0,0 +1,17 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticObserver; + +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticObserver; +import jakarta.enterprise.inject.spi.EventContext; + +import java.util.ArrayList; +import java.util.List; + +public class MyObserver implements SyntheticObserver { + static final List observed = new ArrayList<>(); + + @Override + public void observe(EventContext event, Parameters params) throws Exception { + observed.add(event.getEvent().payload + " with " + params.get("name", String.class)); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyQualifier.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyQualifier.java new file mode 100644 index 0000000000..3827309042 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyQualifier.java @@ -0,0 +1,11 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticObserver; + +import jakarta.inject.Qualifier; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface MyQualifier { +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyService.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyService.java new file mode 100644 index 0000000000..5d97550518 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/MyService.java @@ -0,0 +1,20 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticObserver; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Event; +import jakarta.inject.Inject; + +@ApplicationScoped +public class MyService { + @Inject + Event unqualifiedEvent; + + @Inject + @MyQualifier + Event qualifiedEvent; + + void fireEvent() { + unqualifiedEvent.fire(new MyEvent("Hello World")); + qualifiedEvent.fire(new MyEvent("Hello Special")); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/SyntheticObserverExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/SyntheticObserverExtension.java new file mode 100644 index 0000000000..768c3484b7 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/SyntheticObserverExtension.java @@ -0,0 +1,20 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticObserver; + +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; + +public class SyntheticObserverExtension implements BuildCompatibleExtension { + @Synthesis + public void synthesize(SyntheticComponents syn) { + syn.addObserver(MyEvent.class) + .priority(10) + .observeWith(MyObserver.class); + + syn.addObserver(MyEvent.class) + .qualifier(MyQualifier.class) + .priority(20) + .withParam("name", "@MyQualifier") + .observeWith(MyObserver.class); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/SyntheticObserverTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/SyntheticObserverTest.java new file mode 100644 index 0000000000..9549b42bd9 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserver/SyntheticObserverTest.java @@ -0,0 +1,38 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticObserver; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.List; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.0") +public class SyntheticObserverTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(SyntheticObserverTest.class) + .withBuildCompatibleExtension(SyntheticObserverExtension.class) + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void test() { + MyService myService = getContextualReference(MyService.class); + myService.fireEvent(); + + List expected = List.of( + "Hello World with null", // unqualified event observed by unqualified observer + "Hello Special with null", // qualified event observed by unqualified observer + "Hello Special with @MyQualifier" // qualified event observed by qualified observer + ); + assertEquals(expected, MyObserver.observed); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/MyData.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/MyData.java new file mode 100644 index 0000000000..a5c8329b07 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/MyData.java @@ -0,0 +1,9 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticObserverOfParameterizedType; + +public class MyData { + final String payload; + + MyData(String payload) { + this.payload = payload; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/MyObserver.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/MyObserver.java new file mode 100644 index 0000000000..aa5b891ed5 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/MyObserver.java @@ -0,0 +1,21 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticObserverOfParameterizedType; + +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticObserver; +import jakarta.enterprise.inject.spi.EventContext; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class MyObserver implements SyntheticObserver> { + static final List observed = new ArrayList<>(); + + @Override + public void observe(EventContext> event, Parameters params) throws Exception { + observed.add(event.getEvent() + .stream() + .map(it -> it.payload) + .collect(Collectors.joining(" "))); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/MyService.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/MyService.java new file mode 100644 index 0000000000..1ef7dc9f67 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/MyService.java @@ -0,0 +1,18 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticObserverOfParameterizedType; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Event; +import jakarta.inject.Inject; + +import java.util.List; + +@ApplicationScoped +public class MyService { + @Inject + Event> event; + + void fireEvent() { + event.fire(List.of(new MyData("Hello"), new MyData("World"))); + event.fire(List.of(new MyData("Hello"), new MyData("again"))); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/SyntheticObserverOfParameterizedTypeExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/SyntheticObserverOfParameterizedTypeExtension.java new file mode 100644 index 0000000000..c27b103cfc --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/SyntheticObserverOfParameterizedTypeExtension.java @@ -0,0 +1,16 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticObserverOfParameterizedType; + +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.inject.build.compatible.spi.Types; + +import java.util.List; + +public class SyntheticObserverOfParameterizedTypeExtension implements BuildCompatibleExtension { + @Synthesis + public void synthesize(SyntheticComponents syn, Types types) { + syn.>addObserver(types.parameterized(List.class, MyData.class)) + .observeWith(MyObserver.class); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/SyntheticObserverOfParameterizedTypeTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/SyntheticObserverOfParameterizedTypeTest.java new file mode 100644 index 0000000000..9fae815577 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticObserverOfParameterizedType/SyntheticObserverOfParameterizedTypeTest.java @@ -0,0 +1,33 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.syntheticObserverOfParameterizedType; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.List; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.0") +public class SyntheticObserverOfParameterizedTypeTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(SyntheticObserverOfParameterizedTypeTest.class) + .withBuildCompatibleExtension(SyntheticObserverOfParameterizedTypeExtension.class) + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void test() { + MyService myService = getContextualReference(MyService.class); + myService.fireEvent(); + + List expected = List.of("Hello World", "Hello again"); + assertEquals(expected, MyObserver.observed); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/validation/ValidationExtension.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/validation/ValidationExtension.java new file mode 100644 index 0000000000..82cec8c406 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/validation/ValidationExtension.java @@ -0,0 +1,12 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.validation; + +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Messages; +import jakarta.enterprise.inject.build.compatible.spi.Validation; + +public class ValidationExtension implements BuildCompatibleExtension { + @Validation + public void validate(Messages msg) { + msg.error("Deployment should fail"); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/validation/ValidationTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/validation/ValidationTest.java new file mode 100644 index 0000000000..582d8a2889 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/build/compatible/extensions/validation/ValidationTest.java @@ -0,0 +1,28 @@ +package org.jboss.cdi.tck.tests.build.compatible.extensions.validation; + +import jakarta.enterprise.inject.spi.DeploymentException; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "4.0") +public class ValidationTest extends AbstractTest { + @Deployment + @ShouldThrowException(DeploymentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClassPackage(ValidationTest.class) + .withBuildCompatibleExtension(ValidationExtension.class) + .build(); + } + + @Test + //@SpecAssertion(section = TODO, id = "TODO") + public void trigger() { + // deployment should fail + } +} diff --git a/pom.xml b/pom.xml index b409ae03d6..c559a5b3f0 100644 --- a/pom.xml +++ b/pom.xml @@ -100,7 +100,7 @@ 4.0.0.Beta2 11 - 2.0.0 + 2.1.0-B1 2.0.0 2.0.0 4.0.0