applyFilter(Collection extends MavenProject> projects) {
+ /**
+ * Filter out whitelisted projects with a big twist:
+ * Assume we have all projects {@code a, b, c} while active are {@code a, c} and relation among all projects
+ * is {@code a -> b -> c}. This method handles well the case for transitive list. But, for non-transitive we need
+ * to "pull in" transitive dependencies of eliminated projects, as for case above, the properly filtered list would
+ * be {@code a -> c}.
+ *
+ * Original code would falsely report {@code a} project as "without dependencies", basically would lose link due
+ * filtering. This causes build ordering issues in concurrent builders.
+ */
+ private List applyFilter(
+ Collection extends MavenProject> projects, boolean transitive, boolean upstream) {
List filtered = new ArrayList<>(projects.size());
-
for (MavenProject project : projects) {
if (whiteList.containsKey(project)) {
filtered.add(project);
+ } else if (!transitive) {
+ filtered.addAll(upstream ? getUpstreamProjects(project, false) : getDownstreamProjects(project, false));
}
}
-
return filtered;
}
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 eb6789c12bff..6cc9b4973324 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
@@ -21,31 +21,27 @@
import javax.inject.Named;
import javax.inject.Provider;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
import java.lang.annotation.Annotation;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
+import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Iterator;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import com.google.inject.AbstractModule;
-import com.google.inject.binder.AnnotatedBindingBuilder;
+import com.google.inject.Binder;
import com.google.inject.name.Names;
+import com.google.inject.spi.ProviderInstanceBinding;
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.Scope;
import org.apache.maven.di.impl.Binding;
import org.apache.maven.di.impl.DIException;
import org.apache.maven.di.impl.Dependency;
@@ -54,76 +50,147 @@
import org.apache.maven.session.scope.internal.SessionScope;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.eclipse.sisu.BeanEntry;
+import org.eclipse.sisu.inject.BeanLocator;
@Named
public class SisuDiBridgeModule extends AbstractModule {
- InjectorImpl injector;
- final Set loaded = new HashSet<>();
+ protected final boolean discover;
+ protected InjectorImpl injector;
+
+ public SisuDiBridgeModule() {
+ this(true);
+ }
+
+ public SisuDiBridgeModule(boolean discover) {
+ this.discover = discover;
+ }
@Override
protected void configure() {
Provider containerProvider = getProvider(PlexusContainer.class);
+ Provider beanLocatorProvider = getProvider(BeanLocator.class);
+ injector = new BridgeInjectorImpl(beanLocatorProvider, binder());
+ bindScope(injector, containerProvider, SessionScoped.class, SessionScope.class);
+ bindScope(injector, containerProvider, MojoExecutionScoped.class, MojoExecutionScope.class);
+ injector.bindInstance(Injector.class, injector);
+ bind(Injector.class).toInstance(injector);
+ bind(SisuDiBridgeModule.class).toInstance(this);
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ if (classLoader == null) {
+ classLoader = getClass().getClassLoader();
+ }
+ if (discover) {
+ injector.discover(classLoader);
+ }
+ }
+
+ private void bindScope(
+ InjectorImpl injector,
+ Provider containerProvider,
+ Class extends Annotation> sa,
+ Class extends Scope> ss) {
+ injector.bindScope(sa, () -> {
+ try {
+ return containerProvider.get().lookup(ss);
+ } catch (ComponentLookupException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
+ static class BridgeInjectorImpl extends InjectorImpl {
+ final Provider locator;
+ final Binder binder;
+
+ BridgeInjectorImpl(Provider locator, Binder binder) {
+ this.locator = locator;
+ this.binder = binder;
+ }
+
+ @Override
+ protected Injector bind(Key key, Binding binding) {
+ super.bind(key, binding);
+ if (key.getQualifier() != null) {
+ com.google.inject.Key k = toGuiceKey(key);
+ this.binder.bind(k).toProvider(new BridgeProvider<>(binding));
+ }
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static com.google.inject.Key toGuiceKey(Key key) {
+ if (key.getQualifier() instanceof String s) {
+ return (com.google.inject.Key) com.google.inject.Key.get(key.getType(), Names.named(s));
+ } else if (key.getQualifier() instanceof Annotation a) {
+ return (com.google.inject.Key) com.google.inject.Key.get(key.getType(), a);
+ } else {
+ return (com.google.inject.Key) com.google.inject.Key.get(key.getType());
+ }
+ }
+
+ static class BindingToBeanEntry extends Binding {
+ private BeanEntry beanEntry;
+
+ BindingToBeanEntry(Key elementType) {
+ super(elementType, Set.of());
+ }
+
+ public BindingToBeanEntry toBeanEntry(BeanEntry beanEntry) {
+ this.beanEntry = beanEntry;
+ return this;
+ }
- injector = new InjectorImpl() {
@Override
- public Supplier getCompiledBinding(Dependency dep) {
- Key key = dep.key();
- Set> res = getBindings(key);
- if (res != null && !res.isEmpty()) {
- List> bindingList = new ArrayList<>(res);
- Comparator> comparing = Comparator.comparing(Binding::getPriority);
- bindingList.sort(comparing.reversed());
- Binding binding = bindingList.get(0);
- return compile(binding);
- }
- if (key.getRawType() == List.class) {
- Set> res2 = getBindings(key.getTypeParameter(0));
- Set> res3 = res2 != null ? new HashSet<>(res2) : new HashSet<>();
- try {
- List l = containerProvider
- .get()
- .lookupList(key.getTypeParameter(0).getRawType());
- l.forEach(o -> res3.add(new Binding.BindingToInstance<>(o)));
- } catch (Throwable e) {
- // ignore
- e.printStackTrace();
- }
- List> list =
- res3.stream().map(this::compile).collect(Collectors.toList());
- //noinspection unchecked
- return () -> (Q) list(list);
- }
- if (key.getRawType() == Map.class) {
- Key> k = key.getTypeParameter(0);
- Key v = key.getTypeParameter(1);
- if (k.getRawType() == String.class) {
- Set> res2 = getBindings(v);
- Set> res3 = res2 != null ? new HashSet<>(res2) : new HashSet<>();
- Map> map = res3.stream()
- .filter(b -> b.getOriginalKey() == null
- || b.getOriginalKey().getQualifier() == null
- || b.getOriginalKey().getQualifier() instanceof String)
- .collect(Collectors.toMap(
- b -> (String)
- (b.getOriginalKey() != null
- ? b.getOriginalKey().getQualifier()
- : null),
- this::compile));
- //noinspection unchecked
- return () -> (Q) map(map);
- }
- }
- try {
- Q t = containerProvider.get().lookup(key.getRawType());
- return compile(new Binding.BindingToInstance<>(t));
- } catch (Throwable e) {
- // ignore
- e.printStackTrace();
- }
- if (dep.optional()) {
- return () -> null;
+ public Supplier compile(Function, Supplier>> compiler) {
+ return beanEntry.getProvider()::get;
+ }
+ }
+
+ class BridgeProvider implements Provider {
+ final Binding binding;
+
+ BridgeProvider(Binding binding) {
+ this.binding = binding;
+ }
+
+ @Override
+ public T get() {
+ return compile(binding).get();
+ }
+ }
+
+ @Override
+ public Supplier getCompiledBinding(Dependency dep) {
+ Key key = dep.key();
+ Class rawType = key.getRawType();
+ if (rawType == List.class) {
+ return getListSupplier(key);
+ } else if (rawType == Map.class) {
+ return getMapSupplier(key);
+ } else {
+ return getBeanSupplier(dep, key);
+ }
+ }
+
+ private Supplier getBeanSupplier(Dependency dep, Key key) {
+ List> list = new ArrayList<>();
+ // Add DI bindings
+ list.addAll(getBindings().getOrDefault(key, Set.of()));
+ // Add Plexus bindings
+ for (var bean : locator.get().locate(toGuiceKey(key))) {
+ if (isPlexusBean(bean)) {
+ list.add(new BindingToBeanEntry<>(key).toBeanEntry(bean));
}
+ }
+ if (!list.isEmpty()) {
+ list.sort(getBindingComparator());
+ //noinspection unchecked
+ return () -> (Q) getInstance(list.iterator().next());
+ } else if (dep.optional()) {
+ return () -> null;
+ } else {
throw new DIException("No binding to construct an instance for key "
+ key.getDisplayString() + ". Existing bindings:\n"
+ getBoundKeys().stream()
@@ -133,80 +200,78 @@ public Supplier getCompiledBinding(Dependency dep) {
.distinct()
.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);
- bind(SisuDiBridgeModule.class).toInstance(this);
- ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
- if (classLoader == null) {
- classLoader = getClass().getClassLoader();
}
- loadFromClassLoader(classLoader);
- injector.getBindings().keySet().stream()
- .filter(k -> k.getQualifier() != null)
- .sorted(Comparator.comparing(k -> k.getRawType().getName()))
- .distinct()
- .forEach(key -> {
- Class> clazz = key.getRawType();
- Class itf = (clazz.isInterface()
- ? null
- : (Class) (clazz.getInterfaces().length > 0 ? clazz.getInterfaces()[0] : clazz));
- if (itf != null) {
- AnnotatedBindingBuilder binder = bind(itf);
- if (key.getQualifier() instanceof String s && !s.isEmpty()) {
- binder.annotatedWith(Names.named(s));
- } else if (key.getQualifier() instanceof Annotation a) {
- binder.annotatedWith(a);
- }
- binder.toProvider(() -> injector.getInstance(clazz));
- }
- });
- }
- public void loadFromClassLoader(ClassLoader classLoader) {
- try {
- for (Iterator 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 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();
+ private Supplier getListSupplier(Key key) {
+ Key elementType = key.getTypeParameter(0);
+ return () -> {
+ List> list = new ArrayList<>();
+ // Add DI bindings
+ list.addAll(getBindings().getOrDefault(elementType, Set.of()));
+ // Add Plexus bindings
+ for (var bean : locator.get().locate(toGuiceKey(elementType))) {
+ if (isPlexusBean(bean)) {
+ list.add(new BindingToBeanEntry<>(elementType).toBeanEntry(bean));
}
- for (String className : lines) {
- try {
- Class> clazz = classLoader.loadClass(className);
- injector.bindImplicit(clazz);
- } catch (ClassNotFoundException e) {
- // ignore
- e.printStackTrace();
- }
+ }
+ //noinspection unchecked
+ return (Q) list(list.stream().sorted(getBindingComparator()).toList(), this::getInstance);
+ };
+ }
+
+ private Supplier getMapSupplier(Key key) {
+ Key> keyType = key.getTypeParameter(0);
+ Key valueType = key.getTypeParameter(1);
+ if (keyType.getRawType() != String.class) {
+ throw new DIException("Only String keys are supported for maps: " + key);
+ }
+ return () -> {
+ var comparator = getBindingComparator();
+ Map> map = new HashMap<>();
+ for (Binding> b : getBindings().getOrDefault(valueType, Set.of())) {
+ String name =
+ b.getOriginalKey() != null && b.getOriginalKey().getQualifier() instanceof String s
+ ? s
+ : "";
+ map.compute(name, (n, ob) -> ob == null || comparator.compare(ob, b) < 0 ? b : ob);
+ }
+ for (var bean : locator.get().locate(toGuiceKey(valueType))) {
+ if (isPlexusBean(bean)) {
+ Binding> b = new BindingToBeanEntry<>(valueType)
+ .toBeanEntry(bean)
+ .prioritize(bean.getRank());
+ String name = bean.getKey() instanceof com.google.inject.name.Named n ? n.value() : "";
+ map.compute(name, (n, ob) -> ob == null || ob.getPriority() < b.getPriority() ? b : ob);
}
}
+ //noinspection unchecked
+ return (Q) map(map, this::getInstance);
+ };
+ }
+
+ private Q getInstance(Binding binding) {
+ return compile(binding).get();
+ }
+
+ private static Comparator> getBindingComparator() {
+ Comparator> comparing = Comparator.comparing(Binding::getPriority);
+ return comparing.reversed();
+ }
+
+ private boolean isPlexusBean(BeanEntry entry) {
+ try {
+ if ("org.eclipse.sisu.inject.LazyBeanEntry"
+ .equals(entry.getClass().getName())) {
+ Field f = entry.getClass().getDeclaredField("binding");
+ f.setAccessible(true);
+ Object b = f.get(entry);
+ return !(b instanceof ProviderInstanceBinding> pib)
+ || !(pib.getUserSuppliedProvider() instanceof BridgeProvider>);
+ }
+ } catch (Exception e) {
+ // ignore
}
- } catch (IOException e) {
- throw new MavenException(e);
+ return true;
}
}
}
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 284fafd6aea0..9938a9c46cac 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
@@ -19,190 +19,36 @@
package org.apache.maven.session.scope.internal;
import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Collection;
-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;
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.name.Named;
/**
* SessionScope
*/
-public class SessionScope implements Scope, org.apache.maven.di.Scope {
-
- private static final Provider SEEDED_KEY_PROVIDER = () -> {
- throw new IllegalStateException();
- };
-
- /**
- * ScopeState
- */
- protected static final class ScopeState {
- private final Map, CachingProvider>> provided = new ConcurrentHashMap<>();
-
- public void seed(Class clazz, Provider value) {
- provided.put(Key.get(clazz), new CachingProvider<>(value));
- }
-
- @SuppressWarnings("unchecked")
- public Provider scope(Key key, Provider unscoped) {
- Provider> provider = provided.computeIfAbsent(key, k -> new CachingProvider<>(unscoped));
- return (Provider) provider;
- }
-
- public Collection> providers() {
- return provided.values();
- }
- }
-
- private final List values = new CopyOnWriteArrayList<>();
-
- public void enter() {
- values.add(0, new ScopeState());
- }
-
- protected ScopeState getScopeState() {
- if (values.isEmpty()) {
- throw new OutOfScopeException("Cannot access session scope outside of a scoping block");
- }
- return values.get(0);
- }
-
- public void exit() {
- if (values.isEmpty()) {
- throw new IllegalStateException();
- }
- values.remove(0);
- }
+public class SessionScope extends org.apache.maven.internal.impl.di.SessionScope implements Scope {
public void seed(Class clazz, Provider value) {
- getScopeState().seed(clazz, value);
- }
-
- public void seed(Class clazz, final T value) {
- seed(clazz, (Provider) () -> value);
+ getScopeState().seed(clazz, value::get);
}
public Provider scope(final Key key, final Provider unscoped) {
- // Lazy evaluating provider
- return () -> {
- if (values.isEmpty()) {
- return createProxy(key, unscoped);
- } else {
- return getScopeState().scope(key, unscoped).get();
- }
- };
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public Supplier scope(org.apache.maven.di.Key key, Annotation scope, Supplier 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 up = unscoped::get;
- Provider p = scope((Key) k, up);
- return p::get;
- }
-
- @SuppressWarnings("unchecked")
- private T createProxy(Key key, Provider unscoped) {
- InvocationHandler dispatcher = (proxy, method, args) -> {
- method.setAccessible(true);
- try {
- return method.invoke(getScopeState().scope(key, unscoped).get(), args);
- } catch (InvocationTargetException e) {
- throw e.getCause();
- }
- };
- Class superType = (Class) key.getTypeLiteral().getRawType();
- Class>[] interfaces = getInterfaces(superType);
- return (T) java.lang.reflect.Proxy.newProxyInstance(superType.getClassLoader(), interfaces, dispatcher);
- }
-
- private Class>[] getInterfaces(Class> superType) {
- if (superType.isInterface()) {
- return new Class>[] {superType};
- } else {
- for (Annotation a : superType.getAnnotations()) {
- Class extends Annotation> annotationType = a.annotationType();
- if ("org.apache.maven.api.di.Typed".equals(annotationType.getName())
- || "org.eclipse.sisu.Typed".equals(annotationType.getName())
- || "javax.enterprise.inject.Typed".equals(annotationType.getName())
- || "jakarta.enterprise.inject.Typed".equals(annotationType.getName())) {
- try {
- Class>[] value =
- (Class>[]) annotationType.getMethod("value").invoke(a);
- if (value.length == 0) {
- value = superType.getInterfaces();
- }
- List> nonInterfaces =
- Stream.of(value).filter(c -> !c.isInterface()).collect(Collectors.toList());
- if (!nonInterfaces.isEmpty()) {
- throw new IllegalArgumentException(
- "The Typed annotation must contain only interfaces but the following types are not: "
- + nonInterfaces);
- }
- return value;
- } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
- throw new IllegalStateException(e);
- }
- }
- }
- throw new IllegalArgumentException("The use of session scoped proxies require "
- + "a org.eclipse.sisu.Typed or javax.enterprise.inject.Typed annotation");
- }
+ Object qualifier = key.getAnnotation() instanceof Named n ? n.value() : key.getAnnotation();
+ org.apache.maven.di.Key k =
+ org.apache.maven.di.Key.ofType(key.getTypeLiteral().getType(), qualifier);
+ return scope(k, unscoped::get)::get;
}
- /**
- * A provider wrapping an existing provider with a cache
- * @param the provided type
- */
- protected static class CachingProvider implements Provider {
- private final Provider provider;
- private volatile T value;
-
- CachingProvider(Provider provider) {
- this.provider = provider;
- }
-
- public T value() {
- return value;
- }
-
- @Override
- public T get() {
- if (value == null) {
- synchronized (this) {
- if (value == null) {
- value = provider.get();
- }
- }
- }
- return value;
- }
- }
-
- @SuppressWarnings({"unchecked"})
- public static Provider seededKeyProvider() {
- return (Provider) SEEDED_KEY_PROVIDER;
+ public static Provider seededKeyProvider(Class extends T> clazz) {
+ return SessionScope.seededKeySupplier(clazz)::get;
}
- public static Provider seededKeyProvider(Class extends T> clazz) {
- return () -> {
- throw new IllegalStateException("No instance of " + clazz.getName() + " is bound to the session scope.");
- };
+ protected boolean isTypeAnnotation(Class extends Annotation> annotationType) {
+ return "org.apache.maven.api.di.Typed".equals(annotationType.getName())
+ || "org.eclipse.sisu.Typed".equals(annotationType.getName())
+ || "javax.enterprise.inject.Typed".equals(annotationType.getName())
+ || "jakarta.enterprise.inject.Typed".equals(annotationType.getName());
}
}
diff --git a/maven-core/src/test/java/org/apache/maven/di/DiTest.java b/maven-core/src/test/java/org/apache/maven/di/DiTest.java
new file mode 100644
index 000000000000..62b84bca3b6d
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/di/DiTest.java
@@ -0,0 +1,271 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.di;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.Injector;
+import com.google.inject.TypeLiteral;
+import org.apache.maven.api.model.Model;
+import org.apache.maven.api.services.Source;
+import org.apache.maven.api.spi.ModelParser;
+import org.apache.maven.api.spi.ModelParserException;
+import org.apache.maven.internal.impl.SisuDiBridgeModule;
+import org.codehaus.plexus.DefaultContainerConfiguration;
+import org.codehaus.plexus.DefaultPlexusContainer;
+import org.codehaus.plexus.PlexusContainer;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIf;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class DiTest {
+
+ // return true to run the test
+ static boolean testShouldNotHaveDuplicates() {
+ return true;
+ }
+
+ @Nested
+ class DiTest1 {
+
+ PlexusContainer container;
+
+ @BeforeEach
+ void setup() throws Exception {
+ container = new DefaultPlexusContainer(
+ new DefaultContainerConfiguration(),
+ new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(ModelParser.class).to(TestModelParser.class);
+ }
+ },
+ new SisuDiBridgeModule(false));
+ }
+
+ @Test
+ void testPlexus() throws Exception {
+ List parsers = container.lookupList(ModelParser.class);
+ assertNotNull(parsers);
+ assertEquals(1, parsers.size());
+ Map parsersMap = container.lookupMap(ModelParser.class);
+ assertNotNull(parsersMap);
+ assertEquals(1, parsersMap.size());
+ }
+
+ @Test
+ void testGuice() throws Exception {
+ List> parsers =
+ container.lookup(Injector.class).findBindingsByType(TypeLiteral.get(ModelParser.class));
+ assertNotNull(parsers);
+ assertEquals(1, parsers.size());
+ }
+
+ @Test
+ void testDI() throws Exception {
+ DiInjected diInjected = new DiInjected();
+ container.lookup(org.apache.maven.di.Injector.class).injectInstance(diInjected);
+ assertNotNull(diInjected.parser);
+ assertNotNull(diInjected.parsers);
+ assertEquals(1, diInjected.parsers.size());
+ assertNotNull(diInjected.parsersMap);
+ assertEquals(1, diInjected.parsersMap.size());
+ }
+
+ static class DiInjected {
+ @org.apache.maven.api.di.Inject
+ ModelParser parser;
+
+ @org.apache.maven.api.di.Inject
+ List parsers;
+
+ @org.apache.maven.api.di.Inject
+ Map parsersMap;
+ }
+
+ @Named
+ @Singleton
+ static class TestModelParser implements ModelParser {
+ @Override
+ public Optional locate(Path dir) {
+ return Optional.empty();
+ }
+
+ @Override
+ public Model parse(Source source, Map options) throws ModelParserException {
+ return null;
+ }
+ }
+ }
+
+ @Nested
+ class DiTest2 {
+
+ PlexusContainer container;
+
+ @BeforeEach
+ void setup() throws Exception {
+ container = new DefaultPlexusContainer(new DefaultContainerConfiguration(), new SisuDiBridgeModule(false) {
+ @Override
+ protected void configure() {
+ super.configure();
+ injector.bindImplicit(TestModelParser.class);
+ }
+ });
+ }
+
+ @Test
+ void testPlexus() throws Exception {
+ List parsers = container.lookupList(ModelParser.class);
+ assertNotNull(parsers);
+ assertEquals(1, parsers.size());
+ Map parsersMap = container.lookupMap(ModelParser.class);
+ assertNotNull(parsersMap);
+ assertEquals(1, parsersMap.size());
+ }
+
+ @Test
+ void testGuice() throws Exception {
+ List> parsers2 =
+ container.lookup(Injector.class).findBindingsByType(TypeLiteral.get(ModelParser.class));
+ assertNotNull(parsers2);
+ assertEquals(1, parsers2.size());
+ }
+
+ @Test
+ @EnabledIf("org.apache.maven.di.DiTest#testShouldNotHaveDuplicates")
+ void testDI() throws Exception {
+ DiInjected diInjected = new DiInjected();
+ container.lookup(org.apache.maven.di.Injector.class).injectInstance(diInjected);
+ assertNotNull(diInjected.parser);
+ assertNotNull(diInjected.parsers);
+ assertEquals(1, diInjected.parsers.size());
+ assertNotNull(diInjected.parsersMap);
+ assertEquals(1, diInjected.parsersMap.size());
+ }
+
+ static class DiInjected {
+ @org.apache.maven.api.di.Inject
+ ModelParser parser;
+
+ @org.apache.maven.api.di.Inject
+ List parsers;
+
+ @org.apache.maven.api.di.Inject
+ Map parsersMap;
+ }
+
+ @org.apache.maven.api.di.Named
+ @org.apache.maven.api.di.Singleton
+ static class TestModelParser implements ModelParser {
+ @Override
+ public Optional locate(Path dir) {
+ return Optional.empty();
+ }
+
+ @Override
+ public Model parse(Source source, Map options) throws ModelParserException {
+ return null;
+ }
+ }
+ }
+
+ @Nested
+ class DiTest3 {
+
+ PlexusContainer container;
+
+ @BeforeEach
+ void setup() throws Exception {
+ container = new DefaultPlexusContainer(new DefaultContainerConfiguration(), new SisuDiBridgeModule(false) {
+ @Override
+ protected void configure() {
+ super.configure();
+ injector.bindImplicit(TestModelParser.class);
+ }
+ });
+ }
+
+ @Test
+ void testPlexus() throws Exception {
+ List parsers = container.lookupList(ModelParser.class);
+ assertNotNull(parsers);
+ assertEquals(1, parsers.size());
+ Map parsersMap = container.lookupMap(ModelParser.class);
+ assertNotNull(parsersMap);
+ assertEquals(1, parsersMap.size());
+ }
+
+ @Test
+ void testGuice() throws Exception {
+ List