1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.internal.impl;
20
21 import javax.inject.Named;
22 import javax.inject.Provider;
23
24 import java.io.BufferedReader;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.lang.annotation.Annotation;
29 import java.net.URL;
30 import java.nio.charset.StandardCharsets;
31 import java.util.ArrayList;
32 import java.util.Comparator;
33 import java.util.HashSet;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Set;
38 import java.util.function.Supplier;
39 import java.util.stream.Collectors;
40
41 import com.google.inject.AbstractModule;
42 import com.google.inject.binder.AnnotatedBindingBuilder;
43 import com.google.inject.name.Names;
44 import org.apache.maven.api.services.MavenException;
45 import org.apache.maven.di.Injector;
46 import org.apache.maven.di.Key;
47 import org.apache.maven.di.impl.Binding;
48 import org.apache.maven.di.impl.DIException;
49 import org.apache.maven.di.impl.InjectorImpl;
50 import org.codehaus.plexus.PlexusContainer;
51
52 @Named
53 class SisuDiBridgeModule extends AbstractModule {
54
55 @Override
56 protected void configure() {
57 Provider<PlexusContainer> containerProvider = getProvider(PlexusContainer.class);
58
59 InjectorImpl injector = new InjectorImpl() {
60 @Override
61 public <Q> Supplier<Q> getCompiledBinding(Key<Q> key) {
62 Set<Binding<Q>> res = getBindings(key);
63 if (res != null && !res.isEmpty()) {
64 List<Binding<Q>> bindingList = new ArrayList<>(res);
65 Comparator<Binding<Q>> comparing = Comparator.comparing(Binding::getPriority);
66 bindingList.sort(comparing.reversed());
67 Binding<Q> binding = bindingList.get(0);
68 return compile(binding);
69 }
70 if (key.getRawType() == List.class) {
71 Set<Binding<Object>> res2 = getBindings(key.getTypeParameter(0));
72 Set<Binding<Object>> res3 = res2 != null ? new HashSet<>(res2) : new HashSet<>();
73 try {
74 List<Object> l = containerProvider
75 .get()
76 .lookupList(key.getTypeParameter(0).getRawType());
77 l.forEach(o -> res3.add(new Binding.BindingToInstance<>(o)));
78 } catch (Throwable e) {
79
80 e.printStackTrace();
81 }
82 List<Supplier<Object>> list =
83 res3.stream().map(this::compile).collect(Collectors.toList());
84
85 return () -> (Q) list(list);
86 }
87 if (key.getRawType() == Map.class) {
88 Key<?> k = key.getTypeParameter(0);
89 Key<Object> v = key.getTypeParameter(1);
90 if (k.getRawType() == String.class) {
91 Set<Binding<Object>> res2 = getBindings(v);
92 Set<Binding<Object>> res3 = res2 != null ? new HashSet<>(res2) : new HashSet<>();
93 Map<String, Supplier<Object>> map = res3.stream()
94 .filter(b -> b.getOriginalKey() == null
95 || b.getOriginalKey().getQualifier() == null
96 || b.getOriginalKey().getQualifier() instanceof String)
97 .collect(Collectors.toMap(
98 b -> (String)
99 (b.getOriginalKey() != null
100 ? b.getOriginalKey().getQualifier()
101 : null),
102 this::compile));
103
104 return () -> (Q) map(map);
105 }
106 }
107 try {
108 Q t = containerProvider.get().lookup(key.getRawType());
109 return compile(new Binding.BindingToInstance<>(t));
110 } catch (Throwable e) {
111
112 e.printStackTrace();
113 }
114 throw new DIException("No binding to construct an instance for key "
115 + key.getDisplayString() + ". Existing bindings:\n"
116 + getBoundKeys().stream()
117 .map(Key::toString)
118 .map(String::trim)
119 .sorted()
120 .distinct()
121 .collect(Collectors.joining("\n - ", " - ", "")));
122 }
123 };
124 injector.bindInstance(Injector.class, injector);
125 bind(Injector.class).toInstance(injector);
126 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
127 if (classLoader == null) {
128 classLoader = getClass().getClassLoader();
129 }
130 try {
131 for (Iterator<URL> it = classLoader
132 .getResources("META-INF/maven/org.apache.maven.api.di.Inject")
133 .asIterator();
134 it.hasNext(); ) {
135 URL url = it.next();
136 List<String> lines;
137 try (InputStream is = url.openStream();
138 BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
139 lines = reader.lines()
140 .map(String::trim)
141 .filter(s -> !s.isEmpty() && !s.startsWith("#"))
142 .toList();
143 }
144 for (String className : lines) {
145 try {
146 Class<?> clazz = classLoader.loadClass(className);
147 injector.bindImplicit(clazz);
148 } catch (ClassNotFoundException e) {
149
150 e.printStackTrace();
151 }
152 }
153 }
154
155 } catch (IOException e) {
156 throw new MavenException(e);
157 }
158 injector.getBindings().keySet().stream()
159 .filter(k -> k.getQualifier() != null)
160 .sorted(Comparator.comparing(k -> k.getRawType().getName()))
161 .distinct()
162 .forEach(key -> {
163 Class<?> clazz = key.getRawType();
164 Class<Object> itf = (clazz.isInterface()
165 ? null
166 : (Class<Object>) (clazz.getInterfaces().length > 0 ? clazz.getInterfaces()[0] : clazz));
167 if (itf != null) {
168 AnnotatedBindingBuilder<Object> binder = bind(itf);
169 if (key.getQualifier() instanceof String s) {
170 binder.annotatedWith(Names.named(s));
171 } else if (key.getQualifier() instanceof Annotation a) {
172 binder.annotatedWith(a);
173 }
174 binder.toProvider(() -> injector.getInstance(clazz));
175 }
176 });
177 }
178 }