diff --git a/pom.xml b/pom.xml
index 7182f9fd79..4dbdca2d62 100644
--- a/pom.xml
+++ b/pom.xml
@@ -255,11 +255,12 @@
4.13.2
- 3.1.0
+ 3.1.0
+ 5.0.0
-
-
- 9.0.90
+
+ 1.1
+ 2.1.1
5.9.2
@@ -757,13 +758,6 @@
com.fasterxml.jackson.module
jackson-module-jsonSchema
${jackson.version}
-
-
-
- javax.validation
- validation-api
-
-
com.fasterxml.jackson.datatype
@@ -958,6 +952,13 @@
3.30.2-GA
+
+
+ jakarta.inject
+ jakarta.inject-api
+ 2.0.1
+
+
@@ -1259,7 +1260,12 @@
javax.servlet
javax.servlet-api
- ${servlet.version}
+ ${javax.servlet.version}
+
+
+ jakarta.servlet
+ jakarta.servlet-api
+ ${jakarta.servlet.version}
provided
@@ -1267,7 +1273,18 @@
javax.websocket
javax.websocket-api
- 1.1
+ ${javax.websocket.version}
+
+
+ jakarta.websocket
+ jakarta.websocket-api
+ ${jakarta.websocket.version}
+ provided
+
+
+ jakarta.websocket
+ jakarta.websocket-client-api
+ ${jakarta.websocket.version}
provided
@@ -1282,24 +1299,30 @@
cssparser
0.9.30
+
+
+ javax.validation
+ validation-api
+ 2.0.1.Final
+
jakarta.validation
jakarta.validation-api
- 2.0.2
+ 3.0.2
org.hibernate.validator
hibernate-validator
- 6.2.5.Final
+ 8.0.1.Final
runtime
- org.mortbay.jasper
- apache-el
- ${apache-el.version}
-
- test
+ org.glassfish.expressly
+ expressly
+ 5.0.0
+
+ provided
@@ -2049,25 +2072,6 @@
-
-
- enforce-jakarta.validation-api
-
- enforce
-
-
- ${xwiki.enforcer.enforce-jakarta.validation-api.skip}
-
-
- true
- Use jakarta.validation:jakarta.validation-api instead
-
- javax.validation:validation-api
-
-
-
-
-
enforce-hibernate-validator
diff --git a/xwiki-commons-core/pom.xml b/xwiki-commons-core/pom.xml
index 36ab2d4d6a..cb80caeb4a 100644
--- a/xwiki-commons-core/pom.xml
+++ b/xwiki-commons-core/pom.xml
@@ -64,6 +64,7 @@
xwiki-commons-websocket
xwiki-commons-xml
xwiki-commons-xstream
+ xwiki-commons-jakartabridge
@@ -249,6 +250,68 @@
+
+
+
+ revapi false positives
+ allowed
+
+ -
+ true
+
java.class.nonFinalClassInheritsFromNewClass
+ class org.xwiki.component.embed.GenericProvider<T>
+ class org.xwiki.component.embed.GenericProvider<T>
+ org.xwiki.component.internal.AbstractGenericProvider<T>
+
+ -
+ true
+
java.class.nonFinalClassInheritsFromNewClass
+ class org.xwiki.component.embed.GenericProvider<T>
+ class org.xwiki.component.embed.GenericProvider<T>
+ org.xwiki.component.internal.JavaXGenericProvider<T>
+
+
+
+
+ Moved to WebSocket 2.1.1
+ highlight
+
+ -
+ true
+
java.class.noLongerImplementsInterface
+ class org.xwiki.websocket.AbstractPartialMessageHandler<T>
+ class org.xwiki.websocket.AbstractPartialMessageHandler<T>
+ javax.websocket.MessageHandler.Partial<T>
+
+ -
+ true
+
java.class.noLongerImplementsInterface
+ class org.xwiki.websocket.AbstractPartialMessageHandler<T>
+ class org.xwiki.websocket.AbstractPartialMessageHandler<T>
+ javax.websocket.MessageHandler
+
+ -
+ true
+
java.class.noLongerImplementsInterface
+ class org.xwiki.websocket.AbstractPartialStringMessageHandler
+ class org.xwiki.websocket.AbstractPartialStringMessageHandler
+ javax.websocket.MessageHandler.Partial<java.lang.String>
+
+ -
+ true
+
java.class.noLongerImplementsInterface
+ class org.xwiki.websocket.AbstractPartialStringMessageHandler
+ class org.xwiki.websocket.AbstractPartialStringMessageHandler
+ javax.websocket.MessageHandler
+
+ -
+ true
+ true
+
java.method.parameterTypeChanged
+ parameter .* org.xwiki.websocket.WebSocketContext::.*
+
+
+
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/pom.xml b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/pom.xml
index 7229e3ba12..bf6ec180eb 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/pom.xml
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/pom.xml
@@ -55,13 +55,17 @@
org.slf4j
slf4j-api
-
+
+ jakarta.inject
+ jakarta.inject-api
+
+
javax.inject
javax.inject
1
+
org.xwiki.commons
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/descriptor/DefaultComponentDependency.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/descriptor/DefaultComponentDependency.java
index 48cacebd9c..5f4a501e4b 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/descriptor/DefaultComponentDependency.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/descriptor/DefaultComponentDependency.java
@@ -26,13 +26,14 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
-
-import javax.inject.Provider;
+import java.util.Set;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.xwiki.component.util.DefaultParameterizedType;
import org.xwiki.component.util.ReflectionUtils;
+import jakarta.inject.Provider;
+
/**
* Default implementation of {@link ComponentDependency}.
*
@@ -42,6 +43,9 @@
*/
public class DefaultComponentDependency extends DefaultComponentRole implements ComponentDependency
{
+ private static final Set> SPECIAL_ROLES =
+ Set.of(List.class, Collection.class, Map.class, javax.inject.Provider.class, Provider.class);
+
/**
* @see #getName()
*/
@@ -115,7 +119,8 @@ public boolean equals(Object object)
{
boolean result;
- // See http://www.technofundo.com/tech/java/equalhash.html for the detail of this algorithm.
+ // See http://www.technofundo.com/tech/java/equalhash.html for the detail of
+ // this algorithm.
if (this == object) {
result = true;
} else {
@@ -192,7 +197,7 @@ public Class getRole()
{
Class mapping = getMappingType();
- if (mapping == List.class || mapping == Collection.class || mapping == Map.class || mapping == Provider.class) {
+ if (SPECIAL_ROLES.contains(mapping)) {
return ReflectionUtils.getTypeClass(ReflectionUtils.getLastTypeGenericArgument(getRoleType()));
} else {
return mapping;
@@ -204,7 +209,7 @@ public void setRole(Class role)
{
Class mapping = getMappingType();
- if (mapping == List.class || mapping == Collection.class || mapping == Map.class || mapping == Provider.class) {
+ if (SPECIAL_ROLES.contains(mapping)) {
Type ownerType;
Class> rawType;
if (getRoleType() instanceof ParameterizedType) {
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/internal/multi/AbstractGenericComponentManager.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/internal/multi/AbstractGenericComponentManager.java
index 0b2f569941..6ea9a20897 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/internal/multi/AbstractGenericComponentManager.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/internal/multi/AbstractGenericComponentManager.java
@@ -21,12 +21,12 @@
import java.lang.reflect.Type;
-import javax.inject.Inject;
-
import org.xwiki.component.descriptor.ComponentDescriptor;
import org.xwiki.component.manager.ComponentManager;
import org.xwiki.component.manager.ComponentRepositoryException;
+import jakarta.inject.Inject;
+
/**
* Generic implementation that creates Component Manager instances based on the generic notion of a key. This is used
* for example by the Wiki Component Manager or the User Component Manager which respectively have a key returning the
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/internal/multi/DefaultComponentManagerManager.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/internal/multi/DefaultComponentManagerManager.java
index 2354c510ff..5ae0edab50 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/internal/multi/DefaultComponentManagerManager.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/internal/multi/DefaultComponentManagerManager.java
@@ -22,14 +22,14 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
import org.xwiki.component.annotation.Component;
import org.xwiki.component.manager.ComponentLookupException;
import org.xwiki.component.manager.ComponentManager;
import org.xwiki.component.namespace.NamespaceUtils;
+import jakarta.inject.Inject;
+import jakarta.inject.Singleton;
+
/**
* Default implementation of {@link ComponentManagerManager}.
*
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/internal/namespace/DefaultNamespaceValidator.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/internal/namespace/DefaultNamespaceValidator.java
index 059f5ba8a3..4d3e6e8d9b 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/internal/namespace/DefaultNamespaceValidator.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/main/java/org/xwiki/component/internal/namespace/DefaultNamespaceValidator.java
@@ -25,17 +25,17 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Provider;
-import javax.inject.Singleton;
-
import org.apache.commons.lang3.StringUtils;
import org.xwiki.component.annotation.Component;
import org.xwiki.component.manager.ComponentManager;
import org.xwiki.component.namespace.NamespaceNotAllowedException;
import org.xwiki.component.namespace.NamespaceValidator;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+import jakarta.inject.Provider;
+import jakarta.inject.Singleton;
+
/**
* Default implementation of {@link NamespaceValidator}.
*
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/descriptor/DefaultComponentRoleTest.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/descriptor/DefaultComponentRoleTest.java
index 69ff9c3130..2dfdf0ade6 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/descriptor/DefaultComponentRoleTest.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/descriptor/DefaultComponentRoleTest.java
@@ -30,7 +30,7 @@
* @version $Id$
* @since 3.3M1
*/
-public class DefaultComponentRoleTest
+class DefaultComponentRoleTest
{
private interface Role
{
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/internal/namespace/DefaultNamespaceValidatorTest.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/internal/namespace/DefaultNamespaceValidatorTest.java
index 77496ca0b3..a003f69a8b 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/internal/namespace/DefaultNamespaceValidatorTest.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/internal/namespace/DefaultNamespaceValidatorTest.java
@@ -34,7 +34,7 @@
*
* @version $Id$
*/
-public class DefaultNamespaceValidatorTest
+class DefaultNamespaceValidatorTest
{
private DefaultNamespaceValidator validator = new DefaultNamespaceValidator();
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/internal/namespace/NamespaceTest.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/internal/namespace/NamespaceTest.java
index ac9e08256b..1e8000d341 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/internal/namespace/NamespaceTest.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/internal/namespace/NamespaceTest.java
@@ -31,7 +31,7 @@
*
* @version $Id$
*/
-public class NamespaceTest
+class NamespaceTest
{
@Test
void equalsAndHashCode()
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/internal/namespace/NamespaceUtilsTest.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/internal/namespace/NamespaceUtilsTest.java
index 3785631bd4..50cc2a14a8 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/internal/namespace/NamespaceUtilsTest.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/internal/namespace/NamespaceUtilsTest.java
@@ -31,7 +31,7 @@
*
* @version $Id$
*/
-public class NamespaceUtilsTest
+class NamespaceUtilsTest
{
@Test
void getPrefix()
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/util/DefaultParameterizedTypeTest.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/util/DefaultParameterizedTypeTest.java
index e0c6ce46f2..a159f33c91 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/util/DefaultParameterizedTypeTest.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/util/DefaultParameterizedTypeTest.java
@@ -32,7 +32,7 @@
*
* @version $Id$
*/
-public class DefaultParameterizedTypeTest
+class DefaultParameterizedTypeTest
{
@Test
void toStringTest()
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/util/ReflectionMethodUtilsTest.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/util/ReflectionMethodUtilsTest.java
index 530f924f32..b1bbafa2a9 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/util/ReflectionMethodUtilsTest.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/util/ReflectionMethodUtilsTest.java
@@ -30,7 +30,7 @@
*
* @version $Id$
*/
-public class ReflectionMethodUtilsTest
+class ReflectionMethodUtilsTest
{
@Test
void testGetMethodParameterAnnotations() throws SecurityException, NoSuchMethodException
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/util/ReflectionUtilsTest.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/util/ReflectionUtilsTest.java
index 93cb1569ed..f742e7d4f5 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/util/ReflectionUtilsTest.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-api/src/test/java/org/xwiki/component/util/ReflectionUtilsTest.java
@@ -46,7 +46,7 @@
*
* @version $Id$
*/
-public class ReflectionUtilsTest
+class ReflectionUtilsTest
{
private static interface TestInterfaceSimple
{
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-archetype/src/main/resources/archetype-resources/src/main/java/internal/DefaultHelloWorld.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-archetype/src/main/resources/archetype-resources/src/main/java/internal/DefaultHelloWorld.java
index 0898332d77..f755c332cb 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-archetype/src/main/resources/archetype-resources/src/main/java/internal/DefaultHelloWorld.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-archetype/src/main/resources/archetype-resources/src/main/java/internal/DefaultHelloWorld.java
@@ -22,7 +22,7 @@
import ${package}.HelloWorld;
import org.xwiki.component.annotation.Component;
-import javax.inject.Singleton;
+import jakarta.inject.Singleton;
/**
* Implementation of a {@code HelloWorld} component.
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-archetype/src/main/resources/archetype-resources/src/main/java/script/HelloWorldScriptService.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-archetype/src/main/resources/archetype-resources/src/main/java/script/HelloWorldScriptService.java
index 9d6e720e78..dcdbe148f8 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-archetype/src/main/resources/archetype-resources/src/main/java/script/HelloWorldScriptService.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-archetype/src/main/resources/archetype-resources/src/main/java/script/HelloWorldScriptService.java
@@ -24,9 +24,9 @@
import ${package}.HelloWorld;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+import jakarta.inject.Singleton;
/**
* Make the HelloWorld API available to scripting.
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/annotation/ComponentAnnotationLoader.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/annotation/ComponentAnnotationLoader.java
index ba180a604d..a424cf0047 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/annotation/ComponentAnnotationLoader.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/annotation/ComponentAnnotationLoader.java
@@ -39,7 +39,7 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
-import javax.inject.Provider;
+import jakarta.inject.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -363,7 +363,11 @@ public Set findComponentRoleTypes(Class> componentClass, Type[] paramete
types.add(interfaceType);
}
- // Handle javax.inject.Provider
+ // Handle javax.inject.Provider (retro-compatibility since **feature-deploy-jakarta**)
+ if (javax.inject.Provider.class.isAssignableFrom(interfaceClass)) {
+ types.add(interfaceType);
+ }
+ // Handle jakarta.inject.Provider
if (Provider.class.isAssignableFrom(interfaceClass)) {
types.add(interfaceType);
}
@@ -444,7 +448,11 @@ public Set> findComponentRoleClasses(Class> componentClass)
}
}
- // Handle javax.inject.Provider
+ // Handle javax.inject.Provider (retro-compatibility since **feature-deploy-jakarta**)
+ if (javax.inject.Provider.class.isAssignableFrom(interfaceClass)) {
+ classes.add(interfaceClass);
+ }
+ // Handle jakarta.inject.Provider
if (Provider.class.isAssignableFrom(interfaceClass)) {
classes.add(interfaceClass);
}
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/annotation/ComponentDescriptorFactory.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/annotation/ComponentDescriptorFactory.java
index 7732adbf4a..683d44fc00 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/annotation/ComponentDescriptorFactory.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/annotation/ComponentDescriptorFactory.java
@@ -26,8 +26,6 @@
import java.util.ServiceLoader;
import javax.annotation.Priority;
-import javax.inject.Named;
-import javax.inject.Singleton;
import org.xwiki.component.descriptor.ComponentDependency;
import org.xwiki.component.descriptor.ComponentDescriptor;
@@ -35,6 +33,9 @@
import org.xwiki.component.descriptor.DefaultComponentDescriptor;
import org.xwiki.component.util.ReflectionUtils;
+import jakarta.inject.Named;
+import jakarta.inject.Singleton;
+
/**
* Constructs a Component Descriptor out of a class definition that contains Annotations.
*
@@ -101,23 +102,32 @@ public List> createComponentDescriptors(Class exten
{
List> descriptors = new ArrayList<>();
- // If there's a @Named annotation, use it and ignore hints specified in the @Component annotation.
+ // If there's a @Named annotation, use it and ignore hints specified in the
+ // @Component annotation.
String[] hints;
Named named = componentClass.getAnnotation(Named.class);
- Component component = componentClass.getAnnotation(Component.class);
if (named != null) {
hints = new String[] {named.value()};
} else {
- // If the Component annotation has several hints specified ignore the default hint value and for each
- // specified hint create a Component Descriptor
- if (component != null && component.hints().length > 0) {
- hints = component.hints();
+ javax.inject.Named legacyNamed = componentClass.getAnnotation(javax.inject.Named.class);
+
+ if (legacyNamed != null) {
+ hints = new String[] {legacyNamed.value()};
} else {
- if (component != null && component.value().trim().length() > 0) {
- hints = new String[] {component.value().trim()};
+ Component component = componentClass.getAnnotation(Component.class);
+
+ // If the Component annotation has several hints specified ignore the default
+ // hint value and for each
+ // specified hint create a Component Descriptor
+ if (component != null && component.hints().length > 0) {
+ hints = component.hints();
} else {
- hints = new String[] {"default"};
+ if (component != null && component.value().trim().length() > 0) {
+ hints = new String[] {component.value().trim()};
+ } else {
+ hints = new String[] {"default"};
+ }
}
}
}
@@ -160,8 +170,10 @@ private ComponentDescriptor createComponentDescriptor(Class extends T>
descriptor.setRoleHintPriority(roleHintPriority);
// Set the injected fields.
- // Note: that we need to find all fields since we can have some inherited fields which are annotated in a
- // superclass. Since Java doesn't offer a method to return all fields we have to traverse all parent classes
+ // Note: that we need to find all fields since we can have some inherited fields
+ // which are annotated in a
+ // superclass. Since Java doesn't offer a method to return all fields we have to
+ // traverse all parent classes
// looking for declared fields.
for (Field field : ReflectionUtils.getAllFields(componentClass)) {
ComponentDependency> dependency = createComponentDependency(field);
@@ -183,17 +195,25 @@ private ComponentInstantiationStrategy createComponentInstantiationStrategy(Clas
// Support both InstantiationStrategy and JSR 330's Singleton annotations.
Singleton singleton = componentClass.getAnnotation(Singleton.class);
+
if (singleton != null) {
strategy = ComponentInstantiationStrategy.SINGLETON;
} else {
- InstantiationStrategy instantiationStrategy = componentClass.getAnnotation(InstantiationStrategy.class);
- if (instantiationStrategy != null) {
- strategy = instantiationStrategy.value();
- } else {
- // TODO: In order to be JSR330 compliant we need to change this behavior and consider components are
- // per lookup when no annotation is specified. Before we can do this we need to modify the full xwiki
- // code base and possibly introduce a configuration option. To be discussed.
+ javax.inject.Singleton legacySingleton = componentClass.getAnnotation(javax.inject.Singleton.class);
+ if (legacySingleton != null) {
strategy = ComponentInstantiationStrategy.SINGLETON;
+ } else {
+ InstantiationStrategy instantiationStrategy = componentClass.getAnnotation(InstantiationStrategy.class);
+ if (instantiationStrategy != null) {
+ strategy = instantiationStrategy.value();
+ } else {
+ // TODO: In order to be JSR330 compliant we need to change this behavior and
+ // consider components are
+ // per lookup when no annotation is specified. Before we can do this we need to
+ // modify the full xwiki
+ // code base and possibly introduce a configuration option. To be discussed.
+ strategy = ComponentInstantiationStrategy.SINGLETON;
+ }
}
}
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/annotation/DefaultComponentDependencyFactory.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/annotation/DefaultComponentDependencyFactory.java
index a41c8e4843..eeab3c5497 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/annotation/DefaultComponentDependencyFactory.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/annotation/DefaultComponentDependencyFactory.java
@@ -21,13 +21,13 @@
import java.lang.reflect.Field;
-import javax.inject.Inject;
-import javax.inject.Named;
-
import org.xwiki.component.descriptor.ComponentDependency;
import org.xwiki.component.descriptor.DefaultComponentDependency;
import org.xwiki.component.util.ReflectionUtils;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+
/**
* Uses {@link javax.inject.Inject} and {@link javax.inject.Named} annotations to recognize a Component Dependency.
*
@@ -39,30 +39,43 @@ public class DefaultComponentDependencyFactory extends AbstractComponentDependen
@Override
public ComponentDependency createComponentDependency(Field field)
{
- DefaultComponentDependency dependency;
+ DefaultComponentDependency dependency = null;
- Inject inject = field.getAnnotation(Inject.class);
- if (inject != null) {
- dependency = new DefaultComponentDependency();
+ if (field.getAnnotation(Inject.class) != null || field.getAnnotation(javax.inject.Inject.class) != null) {
+ dependency = createDependency(field);
+ } else {
+ dependency = null;
+ }
- Class> fieldClass = field.getType();
- if (ReflectionUtils.getDirectAnnotation(ComponentRole.class, fieldClass) != null
- && ReflectionUtils.getDirectAnnotation(Role.class, fieldClass) == null) {
- // since 4.0M1, retro-compatibility (generic type used to not be taken into account)
- dependency.setRoleType(fieldClass);
- } else {
- dependency.setRoleType(field.getGenericType());
- }
+ return dependency;
+ }
- dependency.setName(field.getName());
+ private DefaultComponentDependency createDependency(Field field)
+ {
+ DefaultComponentDependency dependency = new DefaultComponentDependency();
- // Look for a Named annotation
- Named named = field.getAnnotation(Named.class);
- if (named != null) {
- dependency.setRoleHint(named.value());
- }
+ Class> fieldClass = field.getType();
+ if (ReflectionUtils.getDirectAnnotation(ComponentRole.class, fieldClass) != null
+ && ReflectionUtils.getDirectAnnotation(Role.class, fieldClass) == null) {
+ // since 4.0M1, retro-compatibility (generic type used to not be taken into
+ // account)
+ dependency.setRoleType(fieldClass);
} else {
- dependency = null;
+ dependency.setRoleType(field.getGenericType());
+ }
+
+ dependency.setName(field.getName());
+
+ // Look for a Named annotation
+ Named named = field.getAnnotation(Named.class);
+ if (named != null) {
+ dependency.setRoleHint(named.value());
+ } else {
+ // Look for legacy Named annotation
+ javax.inject.Named legacyNamed = field.getAnnotation(javax.inject.Named.class);
+ if (legacyNamed != null) {
+ dependency.setRoleHint(legacyNamed.value());
+ }
}
return dependency;
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/embed/EmbeddableComponentManager.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/embed/EmbeddableComponentManager.java
index 6d0a20404a..a6a5e34be1 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/embed/EmbeddableComponentManager.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/embed/EmbeddableComponentManager.java
@@ -19,6 +19,7 @@
*/
package org.xwiki.component.embed;
+import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
@@ -31,8 +32,6 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import javax.inject.Provider;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xwiki.collection.internal.PriorityEntries;
@@ -42,6 +41,10 @@
import org.xwiki.component.descriptor.ComponentDescriptor;
import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
import org.xwiki.component.descriptor.DefaultComponentDescriptor;
+import org.xwiki.component.internal.JakartaGenericProvider;
+import org.xwiki.component.internal.JakartaJavaXProvider;
+import org.xwiki.component.internal.JavaXGenericProvider;
+import org.xwiki.component.internal.JavaXJakartaProvider;
import org.xwiki.component.internal.RoleHint;
import org.xwiki.component.manager.ComponentEventManager;
import org.xwiki.component.manager.ComponentLifecycleException;
@@ -51,8 +54,11 @@
import org.xwiki.component.manager.ComponentRepositoryException;
import org.xwiki.component.manager.NamespacedComponentManager;
import org.xwiki.component.phase.Disposable;
+import org.xwiki.component.util.DefaultParameterizedType;
import org.xwiki.component.util.ReflectionUtils;
+import jakarta.inject.Provider;
+
/**
* Simple implementation of {@link ComponentManager} to be used when using some XWiki modules standalone.
*
@@ -277,7 +283,7 @@ public boolean hasComponent(Type role)
@Override
public boolean hasComponent(Type roleType, String roleHint)
{
- if (getComponentEntry(roleType, roleHint) != null) {
+ if (getComponentEntry(roleType, roleHint, true) != null) {
return true;
}
@@ -295,10 +301,11 @@ public T getInstance(Type roleType, String roleHint) throws ComponentLookupE
{
T instance;
- ComponentEntry componentEntry = (ComponentEntry) getComponentEntry(roleType, roleHint);
+ ComponentEntry componentEntry = (ComponentEntry) getComponentEntry(roleType, roleHint, true);
if (componentEntry == null) {
if (getParent() != null) {
+ // Try the parent
instance = getParent().getInstance(roleType, roleHint);
} else {
throw new ComponentLookupException(
@@ -417,7 +424,7 @@ private T getMapInstance(ComponentEntry roleEntry) throws ComponentLookup
{
try {
return getComponentInstance(roleEntry);
- } catch (Exception|Error e) {
+ } catch (Exception | Error e) {
if (roleEntry.descriptor.isMandatory()) {
throw new ComponentLookupException("Failed to lookup component with type ["
+ roleEntry.descriptor.getRoleType() + "] and hint [" + roleEntry.descriptor.getRoleHint() + "]",
@@ -431,10 +438,63 @@ private T getMapInstance(ComponentEntry roleEntry) throws ComponentLookup
return null;
}
+ private ComponentEntry> tryOtherProvider(Type roleType, String roleHint)
+ {
+ ComponentEntry> entry = null;
+
+ if (roleType instanceof ParameterizedType) {
+ ParameterizedType parameterizedRoleType = (ParameterizedType) roleType;
+
+ if (parameterizedRoleType.getRawType() == Provider.class) {
+ // Try to get the javax version of the provider
+ ParameterizedType javaxProviderType = new DefaultParameterizedType(null, javax.inject.Provider.class,
+ parameterizedRoleType.getActualTypeArguments()[0]);
+ ComponentEntry> javaxEntry = getComponentEntry(javaxProviderType, roleHint);
+
+ if (javaxEntry != null) {
+ // Wrap it as a jakarta provider
+ DefaultComponentDescriptor descriptor = new DefaultComponentDescriptor<>(javaxEntry.descriptor);
+ descriptor.setRoleType(Provider.class);
+ descriptor.setImplementation(JavaXJakartaProvider.class);
+
+ entry = new ComponentEntry(descriptor, new JavaXJakartaProvider(this, javaxProviderType, roleHint));
+ }
+ } else if (parameterizedRoleType.getRawType() == javax.inject.Provider.class) {
+ // Try to get the jakarta version of the provider
+ ParameterizedType jakartaProviderType = new DefaultParameterizedType(null, Provider.class,
+ parameterizedRoleType.getActualTypeArguments()[0]);
+ ComponentEntry> jakartaEntry = getComponentEntry(jakartaProviderType, roleHint);
+
+ if (jakartaEntry != null) {
+ // Wrap it as a javax provider
+ DefaultComponentDescriptor descriptor = new DefaultComponentDescriptor<>(jakartaEntry.descriptor);
+ descriptor.setRoleType(javax.inject.Provider.class);
+ descriptor.setImplementation(JakartaJavaXProvider.class);
+
+ entry =
+ new ComponentEntry(descriptor, new JakartaJavaXProvider(this, jakartaProviderType, roleHint));
+ }
+ }
+ }
+
+ return entry;
+ }
+
+ private ComponentEntry> getComponentEntry(Type role, String hint, boolean javaxBridge)
+ {
+ ComponentEntry> entry = getComponentEntry(role, hint);
+
+ if (entry == null && javaxBridge) {
+ // Retro compatibility: proxy javax or jakarta Provider to the other side
+ entry = tryOtherProvider(role, hint);
+ }
+
+ return entry;
+ }
+
private ComponentEntry> getComponentEntry(Type role, String hint)
{
ComponentEntries> entries = this.componentEntries.get(role);
-
if (entries != null) {
return entries.get(hint != null ? hint : RoleHint.DEFAULT_HINT);
}
@@ -561,42 +621,57 @@ protected Object getDependencyInstance(ComponentDescriptor> descriptor, Object
// Handle different field types
Object fieldValue;
- // Step 1: Verify if there's a Provider registered for the field type
- // - A Provider is a component like any other (except it cannot have a field produced by itself!)
- // - A Provider must implement the JSR330 Producer interface
- //
- // Step 2: Handle Logger injection.
- //
- // Step 3: No producer found, handle scalar and collection types by looking up standard component
- // implementations.
-
- Class> dependencyRoleClass = ReflectionUtils.getTypeClass(dependency.getRoleType());
-
- if (dependencyRoleClass.isAssignableFrom(Logger.class)) {
- fieldValue = createLogger(parentInstance.getClass());
- } else if (dependencyRoleClass.isAssignableFrom(List.class)) {
- fieldValue = getInstanceList(ReflectionUtils.getLastTypeGenericArgument(dependency.getRoleType()));
- } else if (dependencyRoleClass.isAssignableFrom(Map.class)) {
- fieldValue = getInstanceMap(ReflectionUtils.getLastTypeGenericArgument(dependency.getRoleType()));
- } else if (dependencyRoleClass.isAssignableFrom(Provider.class)) {
- // Check if there's a Provider registered for the type
- if (hasComponent(dependency.getRoleType(), dependency.getRoleHint())) {
- fieldValue = getInstance(dependency.getRoleType(), dependency.getRoleHint());
+ ComponentEntry> dependencyEntry = getComponentEntry(dependency.getRoleType(), dependency.getRoleHint(), true);
+
+ if (dependencyEntry != null) {
+ // There is a component explicitly registered for this role type
+ fieldValue = getInstance(dependency.getRoleType(), dependency.getRoleHint());
+ } else {
+ // There is no component explicitly registered for this role type, check for various types with a special
+ // meaning
+ Class> dependencyRoleClass = ReflectionUtils.getTypeClass(dependency.getRoleType());
+
+ if (dependencyRoleClass.isAssignableFrom(Logger.class)) {
+ fieldValue = createLogger(parentInstance.getClass());
+ } else if (dependencyRoleClass.isAssignableFrom(List.class)) {
+ fieldValue = getInstanceList(ReflectionUtils.getLastTypeGenericArgument(dependency.getRoleType()));
+ } else if (dependencyRoleClass.isAssignableFrom(Map.class)) {
+ fieldValue = getInstanceMap(ReflectionUtils.getLastTypeGenericArgument(dependency.getRoleType()));
+ } else if (dependencyRoleClass.isAssignableFrom(Provider.class)) {
+ // Check if there's a Provider registered for the type
+ if (hasComponent(dependency.getRoleType(), dependency.getRoleHint())) {
+ fieldValue = getInstance(dependency.getRoleType(), dependency.getRoleHint());
+ } else {
+ fieldValue = createJakartaGenericProvider(descriptor, dependency);
+ }
+ } else if (dependencyRoleClass.isAssignableFrom(javax.inject.Provider.class)) {
+ // Check if there's a Provider registered for the type
+ if (hasComponent(dependency.getRoleType(), dependency.getRoleHint())) {
+ fieldValue = getInstance(dependency.getRoleType(), dependency.getRoleHint());
+ } else {
+ fieldValue = createGenericProvider(descriptor, dependency);
+ }
+ } else if (dependencyRoleClass.isAssignableFrom(ComponentDescriptor.class)) {
+ fieldValue = new DefaultComponentDescriptor<>(descriptor);
} else {
- fieldValue = createGenericProvider(descriptor, dependency);
+ fieldValue = getInstance(dependency.getRoleType(), dependency.getRoleHint());
}
- } else if (dependencyRoleClass.isAssignableFrom(ComponentDescriptor.class)) {
- fieldValue = new DefaultComponentDescriptor<>(descriptor);
- } else {
- fieldValue = getInstance(dependency.getRoleType(), dependency.getRoleHint());
}
return fieldValue;
}
- protected Provider> createGenericProvider(ComponentDescriptor> descriptor, ComponentDependency> dependency)
+ protected javax.inject.Provider> createGenericProvider(ComponentDescriptor> descriptor,
+ ComponentDependency> dependency)
+ {
+ return new JavaXGenericProvider<>(this, new RoleHint<>(
+ ReflectionUtils.getLastTypeGenericArgument(dependency.getRoleType()), dependency.getRoleHint()));
+ }
+
+ protected Provider> createJakartaGenericProvider(ComponentDescriptor> descriptor,
+ ComponentDependency> dependency)
{
- return new GenericProvider<>(this, new RoleHint<>(
+ return new JakartaGenericProvider<>(this, new RoleHint<>(
ReflectionUtils.getLastTypeGenericArgument(dependency.getRoleType()), dependency.getRoleHint()));
}
@@ -657,7 +732,7 @@ public void registerComponent(ComponentDescriptor componentDescriptor) th
public void registerComponent(ComponentDescriptor componentDescriptor, T componentInstance)
{
ComponentEntry> componentEntry =
- getComponentEntry(componentDescriptor.getRoleType(), componentDescriptor.getRoleHint());
+ getComponentEntry(componentDescriptor.getRoleType(), componentDescriptor.getRoleHint(), true);
if (componentEntry == null
|| componentEntry.descriptor.getRoleHintPriority() >= componentDescriptor.getRoleHintPriority()) {
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/embed/GenericProvider.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/AbstractGenericProvider.java
similarity index 64%
rename from xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/embed/GenericProvider.java
rename to xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/AbstractGenericProvider.java
index 26dea6cd43..5cd98efb8a 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/embed/GenericProvider.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/AbstractGenericProvider.java
@@ -17,21 +17,20 @@
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
-package org.xwiki.component.embed;
+package org.xwiki.component.internal;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
-import javax.inject.Provider;
-
import org.xwiki.component.annotation.ComponentRole;
import org.xwiki.component.annotation.Role;
-import org.xwiki.component.internal.RoleHint;
import org.xwiki.component.manager.ComponentLookupException;
import org.xwiki.component.manager.ComponentManager;
import org.xwiki.component.util.ReflectionUtils;
+import jakarta.inject.Provider;
+
/**
* Default provider used when the Component Manager needs to inject a {@link Provider} field but no custom Provider has
* been registered. The default behavior is simply to look up the Component role class when
@@ -39,17 +38,17 @@
*
* @param the role type
* @version $Id$
- * @since 3.3M2
+ * @since 42.0.0
*/
-public class GenericProvider implements Provider
+public abstract class AbstractGenericProvider
{
/**
- * @see GenericProvider#GenericProvider(ComponentManager, RoleHint)
+ * @see AbstractGenericProvider#GenericProvider(ComponentManager, RoleHint)
*/
protected ComponentManager componentManager;
/**
- * @see GenericProvider#GenericProvider(ComponentManager, RoleHint)
+ * @see AbstractGenericProvider#GenericProvider(ComponentManager, RoleHint)
*/
private RoleHint roleHint;
@@ -58,13 +57,21 @@ public class GenericProvider implements Provider
* {@link javax.inject.Provider#get()}
* @param roleHint the Component Role and Hint that uniquely identify the Component we wish to provide for
*/
- public GenericProvider(ComponentManager componentManager, RoleHint roleHint)
+ AbstractGenericProvider(ComponentManager componentManager, RoleHint roleHint)
{
this.componentManager = componentManager;
this.roleHint = roleHint;
}
- @Override
+ /**
+ * Provides a fully-constructed and injected instance of {@code T}.
+ *
+ * @return instance of {@code T}.
+ * @throws RuntimeException if the injector encounters an error while providing an instance. For example, if an
+ * injectable member on {@code T} throws an exception, the injector may wrap the exception and throw it
+ * to the caller of {@code get()}. Callers should not try to handle such exceptions as the behavior may
+ * vary across injector implementations and even different configurations of the same injector.
+ */
@SuppressWarnings("unchecked")
public T get()
{
@@ -73,25 +80,21 @@ public T get()
try {
Class roleClass = this.roleHint.getRoleClass();
- if (roleClass.isAssignableFrom(Provider.class)) {
+ if (roleClass.isAssignableFrom(Provider.class) || roleClass.isAssignableFrom(javax.inject.Provider.class)) {
try {
- component =
- this.componentManager.getInstance(this.roleHint.getRoleType(), this.roleHint.getHint());
+ component = this.componentManager.getInstance(this.roleHint.getRoleType(), this.roleHint.getHint());
} catch (ComponentLookupException e) {
// Inject a default Provider
- component =
- (T) new GenericProvider<>(this.componentManager, new RoleHint<>(
- ReflectionUtils.getLastTypeGenericArgument(this.roleHint.getRoleType()),
+ component = (T) newProvider(this.componentManager,
+ new RoleHint<>(ReflectionUtils.getLastTypeGenericArgument(this.roleHint.getRoleType()),
this.roleHint.getHint()));
}
} else if (roleClass.isAssignableFrom(List.class)) {
- component =
- (T) this.componentManager.getInstanceList(ReflectionUtils.getLastTypeGenericArgument(this.roleHint
- .getRoleType()));
+ component = (T) this.componentManager
+ .getInstanceList(ReflectionUtils.getLastTypeGenericArgument(this.roleHint.getRoleType()));
} else if (roleClass.isAssignableFrom(Map.class)) {
- component =
- (T) this.componentManager.getInstanceMap(ReflectionUtils.getLastTypeGenericArgument(this.roleHint
- .getRoleType()));
+ component = (T) this.componentManager
+ .getInstanceMap(ReflectionUtils.getLastTypeGenericArgument(this.roleHint.getRoleType()));
} else if (ReflectionUtils.getDirectAnnotation(ComponentRole.class, roleClass) != null
&& ReflectionUtils.getDirectAnnotation(Role.class, roleClass) == null) {
// since 4.0M1, retro-compatibility (generic type used to not be taken into account)
@@ -106,6 +109,8 @@ public T get()
return component;
}
+ protected abstract AbstractGenericProvider newProvider(ComponentManager componentManager, RoleHint roleHint);
+
protected T getInstance(Type type, String hint) throws ComponentLookupException
{
return this.componentManager.getInstance(type, hint);
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/ContextComponentManagerProvider.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/ContextComponentManagerProvider.java
index 369678276a..159e51b656 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/ContextComponentManagerProvider.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/ContextComponentManagerProvider.java
@@ -19,17 +19,17 @@
*/
package org.xwiki.component.internal;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Provider;
-import javax.inject.Singleton;
-
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.xwiki.component.annotation.Component;
import org.xwiki.component.manager.ComponentLookupException;
import org.xwiki.component.manager.ComponentManager;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+import jakarta.inject.Provider;
+import jakarta.inject.Singleton;
+
/**
* Provide the {@link ComponentManager} associated to the current context. Return the root {@link ComponentManager} if
* no context oriented {@link ComponentManager} can be found.
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/JakartaGenericProvider.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/JakartaGenericProvider.java
new file mode 100644
index 0000000000..e93cbc50fd
--- /dev/null
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/JakartaGenericProvider.java
@@ -0,0 +1,52 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.component.internal;
+
+import org.xwiki.component.manager.ComponentManager;
+
+import jakarta.inject.Provider;
+
+/**
+ * Default provider used when the Component Manager needs to inject a {@link Provider} field but no custom Provider has
+ * been registered. The default behavior is simply to look up the Component role class when {@link Provider#get()} is
+ * called. This is useful for example when you wish to do "lazy injection".
+ *
+ * @param the role type
+ * @version $Id$
+ * @since 42.0.0
+ */
+public class JakartaGenericProvider extends AbstractGenericProvider implements Provider
+{
+ /**
+ * @param componentManager the Component Manager instance that we'll use to look up the Component Role during
+ * {@link javax.inject.Provider#get()}
+ * @param roleHint the Component Role and Hint that uniquely identify the Component we wish to provide for
+ */
+ public JakartaGenericProvider(ComponentManager componentManager, RoleHint roleHint)
+ {
+ super(componentManager, roleHint);
+ }
+
+ @Override
+ protected AbstractGenericProvider newProvider(ComponentManager componentManager, RoleHint roleHint)
+ {
+ return new JakartaGenericProvider<>(componentManager, roleHint);
+ }
+}
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/JakartaJavaXProvider.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/JakartaJavaXProvider.java
new file mode 100644
index 0000000000..06fb13cd68
--- /dev/null
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/JakartaJavaXProvider.java
@@ -0,0 +1,70 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.component.internal;
+
+import java.lang.reflect.Type;
+
+import javax.inject.Provider;
+
+import org.xwiki.component.manager.ComponentLookupException;
+import org.xwiki.component.manager.ComponentManager;
+
+/**
+ * Wrapper used to expose a {@link Provider} as a {@link javax.inject.Provider}.
+ *
+ * @param the role type to provide
+ * @version $Id$
+ * @since 42.0.0
+ */
+public class JakartaJavaXProvider implements Provider
+{
+ private final ComponentManager componentManager;
+
+ private final Type providerType;
+
+ private final String roleHint;
+
+ /**
+ * @param componentManager the Component Manager instance to use to get the wrapped {@link jakarta.inject.Provider}
+ * @param providerType the role type to provide
+ * @param roleHint the hint that differentiates a component implementation from another one (each component is
+ * registered with a hint; the "default" hint being the default)
+ */
+ public JakartaJavaXProvider(ComponentManager componentManager, Type providerType, String roleHint)
+ {
+ this.componentManager = componentManager;
+ this.providerType = providerType;
+ this.roleHint = roleHint;
+ }
+
+ @Override
+ public T get()
+ {
+ jakarta.inject.Provider provider;
+ try {
+ provider = this.componentManager.getInstance(this.providerType, this.roleHint);
+ } catch (ComponentLookupException e) {
+ throw new RuntimeException(
+ "Failed to get the provider [" + this.providerType + "] with role hint [" + this.roleHint + "]", e);
+ }
+
+ return provider.get();
+ }
+}
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/JavaXGenericProvider.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/JavaXGenericProvider.java
new file mode 100644
index 0000000000..d3ee08c921
--- /dev/null
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/JavaXGenericProvider.java
@@ -0,0 +1,52 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.component.internal;
+
+import javax.inject.Provider;
+
+import org.xwiki.component.manager.ComponentManager;
+
+/**
+ * Default provider used when the Component Manager needs to inject a {@link Provider} field but no custom Provider has
+ * been registered. The default behavior is simply to look up the Component role class when {@link Provider#get()} is
+ * called. This is useful for example when you wish to do "lazy injection".
+ *
+ * @param the role type
+ * @version $Id$
+ * @since 42.0.0
+ */
+public class JavaXGenericProvider extends AbstractGenericProvider implements Provider
+{
+ /**
+ * @param componentManager the Component Manager instance that we'll use to look up the Component Role during
+ * {@link javax.inject.Provider#get()}
+ * @param roleHint the Component Role and Hint that uniquely identify the Component we wish to provide for
+ */
+ public JavaXGenericProvider(ComponentManager componentManager, RoleHint roleHint)
+ {
+ super(componentManager, roleHint);
+ }
+
+ @Override
+ protected AbstractGenericProvider newProvider(ComponentManager componentManager, RoleHint roleHint)
+ {
+ return new JavaXGenericProvider<>(componentManager, roleHint);
+ }
+}
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/JavaXJakartaProvider.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/JavaXJakartaProvider.java
new file mode 100644
index 0000000000..cfc3df76a8
--- /dev/null
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/JavaXJakartaProvider.java
@@ -0,0 +1,70 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.component.internal;
+
+import java.lang.reflect.Type;
+
+import org.xwiki.component.manager.ComponentLookupException;
+import org.xwiki.component.manager.ComponentManager;
+
+import jakarta.inject.Provider;
+
+/**
+ * Wrapper used to expose a {@link Provider} as a {@link javax.inject.Provider}.
+ *
+ * @param the role type to provide
+ * @version $Id$
+ * @since 42.0.0
+ */
+public class JavaXJakartaProvider implements Provider
+{
+ private final ComponentManager componentManager;
+
+ private final Type providerType;
+
+ private final String roleHint;
+
+ /**
+ * @param componentManager the Component Manager instance to use to get the wrapped {@link jakarta.inject.Provider}
+ * @param providerType the role type to provide
+ * @param roleHint the hint that differentiates a component implementation from another one (each component is
+ * registered with a hint; the "default" hint being the default)
+ */
+ public JavaXJakartaProvider(ComponentManager componentManager, Type providerType, String roleHint)
+ {
+ this.componentManager = componentManager;
+ this.providerType = providerType;
+ this.roleHint = roleHint;
+ }
+
+ @Override
+ public T get()
+ {
+ javax.inject.Provider provider;
+ try {
+ provider = this.componentManager.getInstance(this.providerType, this.roleHint);
+ } catch (ComponentLookupException e) {
+ throw new RuntimeException(
+ "Failed to get the provider [" + this.providerType + "] with role hint [" + this.roleHint + "]", e);
+ }
+
+ return provider.get();
+ }
+}
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/RootComponentManager.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/RootComponentManager.java
index ea5d36753c..80c299be59 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/RootComponentManager.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/RootComponentManager.java
@@ -19,16 +19,16 @@
*/
package org.xwiki.component.internal;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
import org.xwiki.component.annotation.Component;
import org.xwiki.component.internal.multi.DelegateComponentManager;
import org.xwiki.component.manager.ComponentManager;
import org.xwiki.component.phase.Initializable;
import org.xwiki.component.phase.InitializationException;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+import jakarta.inject.Singleton;
+
/**
* Allow injecting the root component manager.
*
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/embed/EmbeddableComponentManagerFactory.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/embed/EmbeddableComponentManagerFactory.java
index 5263d3fbe3..8749b8fbeb 100644
--- a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/embed/EmbeddableComponentManagerFactory.java
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/main/java/org/xwiki/component/internal/embed/EmbeddableComponentManagerFactory.java
@@ -19,14 +19,14 @@
*/
package org.xwiki.component.internal.embed;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
import org.xwiki.component.annotation.Component;
import org.xwiki.component.embed.EmbeddableComponentManager;
import org.xwiki.component.internal.multi.ComponentManagerFactory;
import org.xwiki.component.manager.ComponentManager;
+import jakarta.inject.Inject;
+import jakarta.inject.Singleton;
+
/**
* Create Component Manager implementation based on the Embeddable Component Manager (i.e. a simple implementation of
* {@link ComponentManager} to be used when using some XWiki modules standalone).
diff --git a/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/test/java/org/xwiki/component/JakartaProviderIntegrationTest.java b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/test/java/org/xwiki/component/JakartaProviderIntegrationTest.java
new file mode 100644
index 0000000000..f7240e634f
--- /dev/null
+++ b/xwiki-commons-core/xwiki-commons-component/xwiki-commons-component-default/src/test/java/org/xwiki/component/JakartaProviderIntegrationTest.java
@@ -0,0 +1,212 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.component;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.List;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Role;
+import org.xwiki.component.descriptor.DefaultComponentDescriptor;
+import org.xwiki.component.embed.EmbeddableComponentManager;
+import org.xwiki.component.embed.EmbeddableComponentManagerTest.RoleImpl;
+import org.xwiki.component.embed.EmbeddableComponentManagerTest.TestRole;
+import org.xwiki.component.manager.ComponentLookupException;
+import org.xwiki.component.manager.ComponentRepositoryException;
+import org.xwiki.component.phase.Initializable;
+import org.xwiki.component.phase.InitializationException;
+import org.xwiki.test.LogLevel;
+import org.xwiki.test.junit5.LogCaptureExtension;
+
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+import jakarta.inject.Provider;
+import jakarta.inject.Singleton;
+
+/**
+ * Validate loading and injection of Providers in a real use case.
+ *
+ * @version $Id$
+ */
+//This class needs to remain public because some interfaces are reused in other tests
+public class JakartaProviderIntegrationTest
+{
+ @RegisterExtension
+ private LogCaptureExtension logCapture = new LogCaptureExtension(LogLevel.ERROR);
+
+ @Role
+ public interface TestComponentRole
+ {
+
+ }
+
+ @Component
+ @Singleton
+ public static class TestComponentWithProviders implements TestComponentRole
+ {
+ @Inject
+ public Provider provider1;
+
+ @Inject
+ @Named("another")
+ public Provider provider12;
+
+ @Inject
+ public Provider provider2;
+
+ @Inject
+ public Provider> providerList;
+
+ @Inject
+ public Provider