Skip to content

Commit

Permalink
Support jakarta.inject / jakarta.annotation in E4 as an alternative
Browse files Browse the repository at this point in the history
The javax.annotation / javax.inject are effectively deprecated as they
are now supersede by the jakarta.inject / jakarta.annotation 2.0 API.

This adds support for E4 to optionally process these annotations as well
so users can migrate their code away from the old namespace.

See eclipse-platform/eclipse.platform.ui#1129
  • Loading branch information
laeubi committed Sep 18, 2023
1 parent 13353c0 commit 19f1a20
Show file tree
Hide file tree
Showing 25 changed files with 99 additions and 70 deletions.
6 changes: 3 additions & 3 deletions debug/org.eclipse.debug.ui.launchview/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.debug.ui.launchview;singleton:=true
Bundle-Version: 1.1.200.qualifier
Bundle-Version: 1.1.300.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui,
Expand All @@ -13,8 +13,8 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.e4.ui.di,
org.eclipse.e4.ui.services
Bundle-RequiredExecutionEnvironment: JavaSE-17
Import-Package: javax.annotation;version="[1.0.0,2.0.0)",
javax.inject;version="[1.0.0,2.0.0)"
Import-Package: jakarta.annotation;version="[2.0.0,3.0.0)",
jakarta.inject;version="[2.0.0,3.0.0)"
Bundle-ActivationPolicy: lazy
Service-Component: OSGI-INF/org.eclipse.debug.ui.launchview.internal.model.LaunchViewModel.xml,
OSGI-INF/org.eclipse.debug.ui.launchview.internal.impl.DebugCoreProvider.xml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@
import java.util.function.Supplier;
import java.util.stream.Collectors;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
Expand Down Expand Up @@ -61,6 +57,10 @@
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.inject.Inject;

public class LaunchViewImpl implements Supplier<Set<ILaunchObject>> {

private static final String CONTEXT_MENU_ID = "LaunchViewContextMenu"; //$NON-NLS-1$
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.e4.core.contexts
Bundle-Version: 1.12.300.qualifier
Bundle-Version: 1.12.400.qualifier
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Bundle-ActivationPolicy: lazy
Require-Bundle: org.eclipse.e4.core.di
Bundle-RequiredExecutionEnvironment: JavaSE-17
Import-Package: javax.inject;version="[1.0.0,2.0.0)",
Import-Package: jakarta.inject;version="[2.0.0,3.0.0)",
javax.inject;version="[1.0.0,2.0.0)",
org.osgi.framework;version="[1.5.0,2.0.0)",
org.osgi.service.event;version="[1.3.0,2.0.0)"
Export-Package: org.eclipse.e4.core.contexts;version="1.7.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Inject;
import javax.inject.Qualifier;

/**
* This annotation can be added to injectable fields ands methods
* to indicate that the injected value should come from the active context.
* This annotation can be added to injectable fields ands methods to indicate
* that the injected value should come from the active context.
*
* @see Inject
* @see javax.inject.Inject
* @see jakarta.inject.Inject
* @see IEclipseContext#activate
* @since 1.3
*/
@Qualifier
@javax.inject.Qualifier
@jakarta.inject.Qualifier
@Documented
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.lang.reflect.Type;
import java.util.Objects;
import java.util.Stack;
import javax.inject.Named;
import org.eclipse.e4.core.contexts.Active;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.contexts.RunAndTrack;
Expand Down Expand Up @@ -189,8 +188,12 @@ else if (targetContext.containsKey(keys[i]))
}

private String getKey(IObjectDescriptor descriptor) {
if (descriptor.hasQualifier(Named.class)) {
Named namedAnnotation = descriptor.getQualifier(Named.class);
if (descriptor.hasQualifier(javax.inject.Named.class)) {
javax.inject.Named namedAnnotation = descriptor.getQualifier(javax.inject.Named.class);
return namedAnnotation.value();
}
if (descriptor.hasQualifier(jakarta.inject.Named.class)) {
jakarta.inject.Named namedAnnotation = descriptor.getQualifier(jakarta.inject.Named.class);
return namedAnnotation.value();
}
Type elementType = descriptor.getDesiredType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: org.eclipse.e4.core.di.annotations
Bundle-Version: 1.8.100.qualifier
Bundle-Version: 1.8.200.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-17
Export-Package: org.eclipse.e4.core.di.annotations;version="1.6.0"
Import-Package: javax.inject;version="[1.0.0,2.0.0)"
Import-Package: jakarta.inject;version="[2.0.0,3.0.0)",
javax.inject;version="[1.0.0,2.0.0)"
Bundle-Vendor: %Bundle-Vendor
Automatic-Module-Name: org.eclipse.e4.core.di.annotations
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

/**
* Specifies that the target class can be created by an injector as needed.
* @since 1.3
*/
@Qualifier
@javax.inject.Qualifier
@jakarta.inject.Qualifier
@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

/**
* This annotation can be applied to methods, fields, and parameters to mark
* them as optional for the dependency injection. Typically, if the injector is
Expand Down Expand Up @@ -53,7 +51,8 @@
*
* @since 1.3
*/
@Qualifier
@javax.inject.Qualifier
@jakarta.inject.Qualifier
@Documented
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RUNTIME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-SymbolicName: org.eclipse.e4.core.di.extensions;singleton:=true
Bundle-Version: 0.18.0.qualifier
Bundle-Version: 0.18.100.qualifier
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-17
Export-Package: org.eclipse.e4.core.di.extensions;version="0.16.0"
Bundle-Localization: fragment
Import-Package: javax.inject;version="[1.0.0,2.0.0)"
Import-Package: jakarta.inject;version="[2.0.0,3.0.0)",
javax.inject;version="[1.0.0,2.0.0)"
Automatic-Module-Name: org.eclipse.e4.core.di.extensions
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

/**
* A method or field of type {@link org.osgi.framework.BundleContext} and
Expand Down Expand Up @@ -53,7 +52,8 @@
*
* @since 0.16
*/
@Qualifier
@javax.inject.Qualifier
@jakarta.inject.Qualifier
@Documented
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

/**
* @since 0.16
*/
@Qualifier
@javax.inject.Qualifier
@jakarta.inject.Qualifier
@Documented
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

/**
* Annotation to use with DI to support dynamics and multiple services
*
* @since 0.16
*/
@Qualifier
@javax.inject.Qualifier
@jakarta.inject.Qualifier
@Documented
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
Expand Down
2 changes: 2 additions & 0 deletions runtime/bundles/org.eclipse.e4.core.di/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Export-Package: org.eclipse.e4.core.di;version="1.7.0",
Require-Bundle: org.eclipse.e4.core.di.annotations;bundle-version="[1.4.0,2.0.0)";visibility:=reexport
Import-Package: javax.annotation;version="[1.3.5,2.0.0)",
javax.inject;version="[1.0.0,2.0.0)",
jakarta.inject;version="[2,3)",
jakarta.annotation;version="[2,3)",
org.eclipse.osgi.framework.log;version="1.1.0",
org.osgi.framework;version="[1.8.0,2.0.0)",
org.osgi.util.tracker;version="[1.5.1,2.0.0)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.inject.Qualifier;

/**
* This interface describes objects created by the dependency injection.
Expand All @@ -24,7 +23,7 @@
* set of optional qualifiers.
* </p>
*
* @see Qualifier
* @see javax.inject.Qualifier
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
* @since 1.7
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
*******************************************************************************/
package org.eclipse.e4.core.internal.di;

import jakarta.inject.Named;
import java.lang.reflect.Field;
import javax.inject.Named;
import org.eclipse.e4.core.di.IInjector;
import org.eclipse.e4.core.di.InjectionException;
import org.eclipse.e4.core.di.annotations.Optional;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
Expand All @@ -38,12 +39,6 @@
import java.util.Set;
import java.util.WeakHashMap;
import java.util.stream.Stream;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.eclipse.e4.core.di.IBinding;
import org.eclipse.e4.core.di.IInjector;
import org.eclipse.e4.core.di.InjectionException;
Expand Down Expand Up @@ -137,9 +132,13 @@ private void internalInject(Object object, PrimaryObjectSupplier objectSupplier,
}
rememberInjectedObject(object, objectSupplier);

// We call @PostConstruct after injection. This means that is is called
// We call @javax.annotation.PostConstruct after injection. This means that is
// is called
// as a part of both #make() and #inject().
processAnnotated(PostConstruct.class, object, object.getClass(), objectSupplier, tempSupplier, new ArrayList<>(5));
processAnnotated(javax.annotation.PostConstruct.class, object, object.getClass(), objectSupplier, tempSupplier,
new ArrayList<>(5));
processAnnotated(jakarta.annotation.PostConstruct.class, object, object.getClass(), objectSupplier,
tempSupplier, new ArrayList<>(5));

// remove references to the temporary suppliers
for (Requestor<?> requestor : requestors) {
Expand Down Expand Up @@ -181,7 +180,10 @@ public void uninject(Object object, PrimaryObjectSupplier objectSupplier) {
try {
if (!forgetInjectedObject(object, objectSupplier))
return; // not injected at this time
processAnnotated(PreDestroy.class, object, object.getClass(), objectSupplier, null, new ArrayList<>(5));
processAnnotated(javax.annotation.PreDestroy.class, object, object.getClass(), objectSupplier, null,
new ArrayList<>(5));
processAnnotated(jakarta.annotation.PreDestroy.class, object, object.getClass(), objectSupplier, null,
new ArrayList<>(5));

ArrayList<Requestor<?>> requestors = new ArrayList<>();
processClassHierarchy(object, objectSupplier, null, true /* track */, false /* inverse order */, requestors);
Expand Down Expand Up @@ -351,7 +353,8 @@ private Object internalMake(Class<?> clazz, PrimaryObjectSupplier objectSupplier
if (shouldDebug)
classesBeingCreated.add(clazz);

boolean isSingleton = isAnnotationPresent(clazz, Singleton.class);
boolean isSingleton = isAnyAnnotationPresent(clazz,
List.of(javax.inject.Singleton.class, jakarta.inject.Singleton.class));
if (isSingleton) {
synchronized (singletonCache) {
if (singletonCache.containsKey(clazz))
Expand All @@ -372,7 +375,9 @@ private Object internalMake(Class<?> clazz, PrimaryObjectSupplier objectSupplier
continue;

// unless this is the default constructor, it has to be tagged
if (!isAnnotationPresent(constructor, Inject.class) && constructor.getParameterTypes().length != 0)
if (!isAnyAnnotationPresent(constructor,
List.of(javax.inject.Inject.class, jakarta.inject.Inject.class))
&& constructor.getParameterTypes().length != 0)
continue;

ConstructorRequestor requestor = new ConstructorRequestor(constructor, this, objectSupplier, tempSupplier);
Expand Down Expand Up @@ -432,7 +437,10 @@ public void disposed(PrimaryObjectSupplier objectSupplier) {
Object object = objects[i];
if (!forgetInjectedObject(object, objectSupplier))
continue; // not injected at this time
processAnnotated(PreDestroy.class, object, object.getClass(), objectSupplier, null, new ArrayList<>(5));
processAnnotated(javax.annotation.PreDestroy.class, object, object.getClass(), objectSupplier, null,
new ArrayList<>(5));
processAnnotated(jakarta.annotation.PreDestroy.class, object, object.getClass(), objectSupplier, null,
new ArrayList<>(5));
}
forgetSupplier(objectSupplier);
}
Expand Down Expand Up @@ -681,8 +689,9 @@ private boolean processFields(Object userObject, PrimaryObjectSupplier objectSup
continue;
injectedStatic = true;
}
if (!isAnnotationPresent(field, Inject.class))
if (!isAnyAnnotationPresent(field, List.of(javax.inject.Inject.class, jakarta.inject.Inject.class))) {
continue;
}
requestors.add(new FieldRequestor(field, this, objectSupplier, tempSupplier, userObject, track));
}
return injectedStatic;
Expand Down Expand Up @@ -723,7 +732,7 @@ private boolean processMethods(final Object userObject, PrimaryObjectSupplier ob
}
injectedStatic = true;
}
if (!isAnnotationPresent(method, Inject.class)) {
if (!isAnyAnnotationPresent(method, List.of(javax.inject.Inject.class, jakarta.inject.Inject.class))) {
continue;
}
requestors.add(new MethodRequestor(method, this, objectSupplier, tempSupplier, userObject, track));
Expand Down Expand Up @@ -839,7 +848,7 @@ private Class<?> getProviderType(Type type) {
if (!(type instanceof ParameterizedType))
return null;
Type rawType = ((ParameterizedType) type).getRawType();
if (!Provider.class.equals(rawType))
if (!javax.inject.Provider.class.equals(rawType) && !jakarta.inject.Provider.class.equals(rawType))
return null;
Type[] actualTypes = ((ParameterizedType) type).getActualTypeArguments();
if (actualTypes.length != 1)
Expand Down Expand Up @@ -888,8 +897,11 @@ private Binding findBinding(IObjectDescriptor descriptor) {
return null;
Set<Binding> collection = bindings.get(desiredClass);
String desiredQualifierName = null;
if (descriptor.hasQualifier(Named.class)) {
Named namedAnnotation = descriptor.getQualifier(Named.class);
if (descriptor.hasQualifier(jakarta.inject.Named.class)) {
jakarta.inject.Named namedAnnotation = descriptor.getQualifier(jakarta.inject.Named.class);
desiredQualifierName = namedAnnotation.value();
} else if (descriptor.hasQualifier(javax.inject.Named.class)) {
javax.inject.Named namedAnnotation = descriptor.getQualifier(javax.inject.Named.class);
desiredQualifierName = namedAnnotation.value();
} else {
Annotation[] annotations = descriptor.getQualifiers();
Expand Down Expand Up @@ -993,6 +1005,16 @@ public void setDefaultSupplier(PrimaryObjectSupplier objectSupplier) {
defaultSupplier = objectSupplier;
}

private boolean isAnyAnnotationPresent(AnnotatedElement annotatedElement,
Collection<Class<? extends Annotation>> annotation) {
for (Class<? extends Annotation> a : annotation) {
if (isAnnotationPresent(annotatedElement, a)) {
return true;
}
}
return false;
}

private boolean isAnnotationPresent(AnnotatedElement annotatedElement,
Class<? extends Annotation> annotation) {
Map<AnnotatedElement, Boolean> cache = annotationsPresent.get(annotation);
Expand Down
Loading

0 comments on commit 19f1a20

Please sign in to comment.