This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/maven.git
commit 8d483f922bacab8b6b774812c570c973d8a53eca Author: Guillaume Nodet <[email protected]> AuthorDate: Mon Jun 10 08:58:25 2024 +0200 [MNG-8152] Implement @SessionScoped and @MojoExecutionScoped from the DI API --- .../org/apache/maven/api/di/MojoExecutionScoped.java | 2 -- .../java/org/apache/maven/api/di/SessionScoped.java | 2 -- .../execution/scope/internal/MojoExecutionScope.java | 16 +++++++++++++++- .../maven/internal/impl/SisuDiBridgeModule.java | 19 +++++++++++++++++++ .../maven/session/scope/internal/SessionScope.java | 16 +++++++++++++++- .../src/main/java/org/apache/maven/di/Injector.java | 3 +++ .../java/org/apache/maven/di/impl/InjectorImpl.java | 9 +++++++-- 7 files changed, 59 insertions(+), 8 deletions(-) diff --git a/api/maven-api-di/src/main/java/org/apache/maven/api/di/MojoExecutionScoped.java b/api/maven-api-di/src/main/java/org/apache/maven/api/di/MojoExecutionScoped.java index b12f9a4159..a3fec5ca81 100644 --- a/api/maven-api-di/src/main/java/org/apache/maven/api/di/MojoExecutionScoped.java +++ b/api/maven-api-di/src/main/java/org/apache/maven/api/di/MojoExecutionScoped.java @@ -30,8 +30,6 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; * Indicates that the annotated bean has a lifespan limited to a given mojo execution, * which means each mojo execution will result in a different instance being injected. * - * TODO: this is currently not implemented - * * @since 4.0.0 */ @Scope diff --git a/api/maven-api-di/src/main/java/org/apache/maven/api/di/SessionScoped.java b/api/maven-api-di/src/main/java/org/apache/maven/api/di/SessionScoped.java index ec4d5a8ea7..eae72f8e2b 100644 --- a/api/maven-api-di/src/main/java/org/apache/maven/api/di/SessionScoped.java +++ b/api/maven-api-di/src/main/java/org/apache/maven/api/di/SessionScoped.java @@ -30,8 +30,6 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; * Indicates that annotated component should be instantiated before session execution starts * and discarded after session execution completes. * - * TODO: this is currently not implemented - * * @since 4.0.0 */ @Scope diff --git a/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScope.java b/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScope.java index b650912f25..a9d9feb65f 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScope.java +++ b/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScope.java @@ -18,16 +18,19 @@ */ package org.apache.maven.execution.scope.internal; +import java.lang.annotation.Annotation; import java.util.Collection; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.LinkedList; import java.util.Map; +import java.util.function.Supplier; import com.google.inject.Key; import com.google.inject.OutOfScopeException; import com.google.inject.Provider; import com.google.inject.Scope; +import com.google.inject.name.Names; import com.google.inject.util.Providers; import org.apache.maven.execution.MojoExecutionEvent; import org.apache.maven.execution.MojoExecutionListener; @@ -37,7 +40,7 @@ import org.apache.maven.plugin.MojoExecutionException; /** * MojoExecutionScope */ -public class MojoExecutionScope implements Scope, MojoExecutionListener { +public class MojoExecutionScope implements Scope, org.apache.maven.di.Scope, MojoExecutionListener { private static final Provider<Object> SEEDED_KEY_PROVIDER = () -> { throw new IllegalStateException(); }; @@ -113,6 +116,17 @@ public class MojoExecutionScope implements Scope, MojoExecutionListener { }; } + @Override + public <T> Supplier<T> scope(org.apache.maven.di.Key<T> key, Annotation scope, Supplier<T> unscoped) { + Object qualifier = key.getQualifier(); + Key k = qualifier != null + ? Key.get(key.getType(), qualifier instanceof String s ? Names.named(s) : (Annotation) qualifier) + : Key.get(key.getType()); + Provider<T> up = unscoped::get; + Provider<T> p = scope(k, up); + return p::get; + } + @SuppressWarnings({"unchecked"}) public static <T> Provider<T> seededKeyProvider() { return (Provider<T>) SEEDED_KEY_PROVIDER; diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/SisuDiBridgeModule.java b/maven-core/src/main/java/org/apache/maven/internal/impl/SisuDiBridgeModule.java index ed569ba420..30423b2c10 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/SisuDiBridgeModule.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/SisuDiBridgeModule.java @@ -41,13 +41,18 @@ import java.util.stream.Collectors; import com.google.inject.AbstractModule; import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.name.Names; +import org.apache.maven.api.di.MojoExecutionScoped; +import org.apache.maven.api.di.SessionScoped; import org.apache.maven.api.services.MavenException; import org.apache.maven.di.Injector; import org.apache.maven.di.Key; import org.apache.maven.di.impl.Binding; import org.apache.maven.di.impl.DIException; import org.apache.maven.di.impl.InjectorImpl; +import org.apache.maven.execution.scope.internal.MojoExecutionScope; +import org.apache.maven.session.scope.internal.SessionScope; import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; @Named class SisuDiBridgeModule extends AbstractModule { @@ -121,6 +126,20 @@ class SisuDiBridgeModule extends AbstractModule { .collect(Collectors.joining("\n - ", " - ", ""))); } }; + injector.bindScope(SessionScoped.class, () -> { + try { + return containerProvider.get().lookup(SessionScope.class); + } catch (ComponentLookupException e) { + throw new RuntimeException(e); + } + }); + injector.bindScope(MojoExecutionScoped.class, () -> { + try { + return containerProvider.get().lookup(MojoExecutionScope.class); + } catch (ComponentLookupException e) { + throw new RuntimeException(e); + } + }); injector.bindInstance(Injector.class, injector); bind(Injector.class).toInstance(injector); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); diff --git a/maven-core/src/main/java/org/apache/maven/session/scope/internal/SessionScope.java b/maven-core/src/main/java/org/apache/maven/session/scope/internal/SessionScope.java index ef60843d9d..71c2add405 100644 --- a/maven-core/src/main/java/org/apache/maven/session/scope/internal/SessionScope.java +++ b/maven-core/src/main/java/org/apache/maven/session/scope/internal/SessionScope.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -33,11 +34,12 @@ import com.google.inject.Key; import com.google.inject.OutOfScopeException; import com.google.inject.Provider; import com.google.inject.Scope; +import com.google.inject.name.Names; /** * SessionScope */ -public class SessionScope implements Scope { +public class SessionScope implements Scope, org.apache.maven.di.Scope { private static final Provider<Object> SEEDED_KEY_PROVIDER = () -> { throw new IllegalStateException(); @@ -103,6 +105,18 @@ public class SessionScope implements Scope { }; } + @SuppressWarnings("unchecked") + @Override + public <T> Supplier<T> scope(org.apache.maven.di.Key<T> key, Annotation scope, Supplier<T> unscoped) { + Object qualifier = key.getQualifier(); + Key<?> k = qualifier != null + ? Key.get(key.getType(), qualifier instanceof String s ? Names.named(s) : (Annotation) qualifier) + : Key.get(key.getType()); + Provider<T> up = unscoped::get; + Provider<T> p = scope((Key<T>) k, up); + return p::get; + } + @SuppressWarnings("unchecked") private <T> T createProxy(Key<T> key, Provider<T> unscoped) { InvocationHandler dispatcher = (proxy, method, args) -> { diff --git a/maven-di/src/main/java/org/apache/maven/di/Injector.java b/maven-di/src/main/java/org/apache/maven/di/Injector.java index 3b2d56d204..9ccc1b698c 100644 --- a/maven-di/src/main/java/org/apache/maven/di/Injector.java +++ b/maven-di/src/main/java/org/apache/maven/di/Injector.java @@ -19,6 +19,7 @@ package org.apache.maven.di; import java.lang.annotation.Annotation; +import java.util.function.Supplier; import org.apache.maven.di.impl.InjectorImpl; @@ -36,6 +37,8 @@ public interface Injector { Injector bindScope(Class<? extends Annotation> scopeAnnotation, Scope scope); + Injector bindScope(Class<? extends Annotation> scopeAnnotation, Supplier<Scope> scope); + Injector bindImplicit(Class<?> cls); <T> Injector bindInstance(Class<T> cls, T instance); diff --git a/maven-di/src/main/java/org/apache/maven/di/impl/InjectorImpl.java b/maven-di/src/main/java/org/apache/maven/di/impl/InjectorImpl.java index 142d2bae96..a92a5765d3 100644 --- a/maven-di/src/main/java/org/apache/maven/di/impl/InjectorImpl.java +++ b/maven-di/src/main/java/org/apache/maven/di/impl/InjectorImpl.java @@ -44,7 +44,7 @@ import org.apache.maven.di.Scope; public class InjectorImpl implements Injector { private final Map<Key<?>, Set<Binding<?>>> bindings = new HashMap<>(); - private final Map<Class<? extends Annotation>, Scope> scopes = new HashMap<>(); + private final Map<Class<? extends Annotation>, Supplier<Scope>> scopes = new HashMap<>(); public InjectorImpl() { bindScope(Singleton.class, new SingletonScope()); @@ -87,6 +87,10 @@ public class InjectorImpl implements Injector { } public Injector bindScope(Class<? extends Annotation> scopeAnnotation, Scope scope) { + return bindScope(scopeAnnotation, () -> scope); + } + + public Injector bindScope(Class<? extends Annotation> scopeAnnotation, Supplier<Scope> scope) { if (scopes.put(scopeAnnotation, scope) != null) { throw new DIException( "Cannot rebind scope annotation class to a different implementation: " + scopeAnnotation); @@ -204,7 +208,8 @@ public class InjectorImpl implements Injector { .map(Map.Entry::getValue) .findFirst() .orElseThrow(() -> new DIException("Scope not bound for annotation " - + binding.getScope().getClass())); + + binding.getScope().annotationType())) + .get(); compiled = scope.scope((Key<Q>) binding.getOriginalKey(), binding.getScope(), compiled); } return compiled;
