You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2024/06/11 07:23:11 UTC
(maven) 02/03: [MNG-8152] Implement @SessionScoped and @MojoExecutionScoped from the DI API
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 <gn...@gmail.com>
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;