[MNG-8220] Fix loading DI-powered beans from extensions (#1683)

This commit is contained in:
Guillaume Nodet 2024-08-29 17:32:53 +02:00 committed by GitHub
parent acec540547
commit 40fe1dc167
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 65 additions and 42 deletions

View File

@ -55,13 +55,16 @@ import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
@Named @Named
class SisuDiBridgeModule extends AbstractModule { public class SisuDiBridgeModule extends AbstractModule {
InjectorImpl injector;
final Set<String> loaded = new HashSet<>();
@Override @Override
protected void configure() { protected void configure() {
Provider<PlexusContainer> containerProvider = getProvider(PlexusContainer.class); Provider<PlexusContainer> containerProvider = getProvider(PlexusContainer.class);
InjectorImpl injector = new InjectorImpl() { injector = new InjectorImpl() {
@Override @Override
public <Q> Supplier<Q> getCompiledBinding(Key<Q> key) { public <Q> Supplier<Q> getCompiledBinding(Key<Q> key) {
Set<Binding<Q>> res = getBindings(key); Set<Binding<Q>> res = getBindings(key);
@ -142,38 +145,12 @@ class SisuDiBridgeModule extends AbstractModule {
}); });
injector.bindInstance(Injector.class, injector); injector.bindInstance(Injector.class, injector);
bind(Injector.class).toInstance(injector); bind(Injector.class).toInstance(injector);
bind(SisuDiBridgeModule.class).toInstance(this);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) { if (classLoader == null) {
classLoader = getClass().getClassLoader(); classLoader = getClass().getClassLoader();
} }
try { loadFromClassLoader(classLoader);
for (Iterator<URL> it = classLoader
.getResources("META-INF/maven/org.apache.maven.api.di.Inject")
.asIterator();
it.hasNext(); ) {
URL url = it.next();
List<String> lines;
try (InputStream is = url.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
lines = reader.lines()
.map(String::trim)
.filter(s -> !s.isEmpty() && !s.startsWith("#"))
.toList();
}
for (String className : lines) {
try {
Class<?> clazz = classLoader.loadClass(className);
injector.bindImplicit(clazz);
} catch (ClassNotFoundException e) {
// ignore
e.printStackTrace();
}
}
}
} catch (IOException e) {
throw new MavenException(e);
}
injector.getBindings().keySet().stream() injector.getBindings().keySet().stream()
.filter(k -> k.getQualifier() != null) .filter(k -> k.getQualifier() != null)
.sorted(Comparator.comparing(k -> k.getRawType().getName())) .sorted(Comparator.comparing(k -> k.getRawType().getName()))
@ -185,7 +162,7 @@ class SisuDiBridgeModule extends AbstractModule {
: (Class<Object>) (clazz.getInterfaces().length > 0 ? clazz.getInterfaces()[0] : clazz)); : (Class<Object>) (clazz.getInterfaces().length > 0 ? clazz.getInterfaces()[0] : clazz));
if (itf != null) { if (itf != null) {
AnnotatedBindingBuilder<Object> binder = bind(itf); AnnotatedBindingBuilder<Object> binder = bind(itf);
if (key.getQualifier() instanceof String s) { if (key.getQualifier() instanceof String s && !s.isEmpty()) {
binder.annotatedWith(Names.named(s)); binder.annotatedWith(Names.named(s));
} else if (key.getQualifier() instanceof Annotation a) { } else if (key.getQualifier() instanceof Annotation a) {
binder.annotatedWith(a); binder.annotatedWith(a);
@ -194,4 +171,37 @@ class SisuDiBridgeModule extends AbstractModule {
} }
}); });
} }
public void loadFromClassLoader(ClassLoader classLoader) {
try {
for (Iterator<URL> it = classLoader
.getResources("META-INF/maven/org.apache.maven.api.di.Inject")
.asIterator();
it.hasNext(); ) {
URL url = it.next();
if (loaded.add(url.toExternalForm())) {
List<String> lines;
try (InputStream is = url.openStream();
BufferedReader reader =
new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
lines = reader.lines()
.map(String::trim)
.filter(s -> !s.isEmpty() && !s.startsWith("#"))
.toList();
}
for (String className : lines) {
try {
Class<?> clazz = classLoader.loadClass(className);
injector.bindImplicit(clazz);
} catch (ClassNotFoundException e) {
// ignore
e.printStackTrace();
}
}
}
}
} catch (IOException e) {
throw new MavenException(e);
}
}
} }

View File

@ -138,7 +138,8 @@ public class SessionScope implements Scope, org.apache.maven.di.Scope {
} else { } else {
for (Annotation a : superType.getAnnotations()) { for (Annotation a : superType.getAnnotations()) {
Class<? extends Annotation> annotationType = a.annotationType(); Class<? extends Annotation> annotationType = a.annotationType();
if ("org.eclipse.sisu.Typed".equals(annotationType.getName()) if ("org.apache.maven.api.di.Typed".equals(annotationType.getName())
|| "org.eclipse.sisu.Typed".equals(annotationType.getName())
|| "javax.enterprise.inject.Typed".equals(annotationType.getName()) || "javax.enterprise.inject.Typed".equals(annotationType.getName())
|| "jakarta.enterprise.inject.Typed".equals(annotationType.getName())) { || "jakarta.enterprise.inject.Typed".equals(annotationType.getName())) {
try { try {

View File

@ -128,8 +128,15 @@ public abstract class Key<T> {
* and prepended qualifier display string if this key has a qualifier. * and prepended qualifier display string if this key has a qualifier.
*/ */
public String getDisplayString() { public String getDisplayString() {
return (qualifier != null ? Utils.getDisplayString(qualifier) + " " : "") return (qualifier != null ? getQualifierDisplayString() + " " : "") + ReflectionUtils.getDisplayName(type);
+ ReflectionUtils.getDisplayName(type); }
private String getQualifierDisplayString() {
if (qualifier instanceof String s) {
return s.isEmpty() ? "@Named" : "@Named(\"" + s + "\")";
}
String s = Utils.getDisplayString(qualifier);
return s;
} }
@Override @Override
@ -155,6 +162,6 @@ public abstract class Key<T> {
@Override @Override
public String toString() { public String toString() {
return (qualifier != null ? qualifier + " " : "") + type.getTypeName(); return getDisplayString();
} }
} }

View File

@ -137,15 +137,18 @@ public class InjectorImpl implements Injector {
current.add(key); current.add(key);
throw new DIException("Circular references: " + current); throw new DIException("Circular references: " + current);
} }
doBindImplicit(key, binding); try {
Class<?> cls = key.getRawType().getSuperclass();
while (cls != Object.class && cls != null) {
key = Key.of(cls, key.getQualifier());
doBindImplicit(key, binding); doBindImplicit(key, binding);
cls = cls.getSuperclass(); Class<?> cls = key.getRawType().getSuperclass();
while (cls != Object.class && cls != null) {
key = Key.of(cls, key.getQualifier());
doBindImplicit(key, binding);
cls = cls.getSuperclass();
}
return this;
} finally {
current.remove(key);
} }
current.remove(key);
return this;
} }
protected <U> Injector bind(Key<U> key, Binding<U> b) { protected <U> Injector bind(Key<U> key, Binding<U> b) {

View File

@ -95,6 +95,7 @@ import org.apache.maven.execution.scope.internal.MojoExecutionScope;
import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule; import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule;
import org.apache.maven.extension.internal.CoreExports; import org.apache.maven.extension.internal.CoreExports;
import org.apache.maven.extension.internal.CoreExtensionEntry; import org.apache.maven.extension.internal.CoreExtensionEntry;
import org.apache.maven.internal.impl.SisuDiBridgeModule;
import org.apache.maven.jline.JLineMessageBuilderFactory; import org.apache.maven.jline.JLineMessageBuilderFactory;
import org.apache.maven.jline.MessageUtils; import org.apache.maven.jline.MessageUtils;
import org.apache.maven.lifecycle.LifecycleExecutionException; import org.apache.maven.lifecycle.LifecycleExecutionException;
@ -715,6 +716,7 @@ public class MavenCli {
new SessionScopeModule(container.lookup(SessionScope.class)), new SessionScopeModule(container.lookup(SessionScope.class)),
new MojoExecutionScopeModule(container.lookup(MojoExecutionScope.class)), new MojoExecutionScopeModule(container.lookup(MojoExecutionScope.class)),
new ExtensionConfigurationModule(extension, extensionSource)); new ExtensionConfigurationModule(extension, extensionSource));
container.lookup(SisuDiBridgeModule.class).loadFromClassLoader(extension.getClassRealm());
} }
customizeContainer(container); customizeContainer(container);