1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.execution.scope.internal;
20
21 import java.lang.annotation.Annotation;
22 import java.util.Collection;
23 import java.util.HashMap;
24 import java.util.IdentityHashMap;
25 import java.util.LinkedList;
26 import java.util.Map;
27 import java.util.function.Supplier;
28
29 import com.google.inject.Key;
30 import com.google.inject.OutOfScopeException;
31 import com.google.inject.Provider;
32 import com.google.inject.Scope;
33 import com.google.inject.name.Names;
34 import com.google.inject.util.Providers;
35 import org.apache.maven.execution.MojoExecutionEvent;
36 import org.apache.maven.execution.MojoExecutionListener;
37 import org.apache.maven.execution.scope.WeakMojoExecutionListener;
38 import org.apache.maven.plugin.MojoExecutionException;
39
40
41
42
43 public class MojoExecutionScope implements Scope, org.apache.maven.di.Scope, MojoExecutionListener {
44 private static final Provider<Object> SEEDED_KEY_PROVIDER = () -> {
45 throw new IllegalStateException();
46 };
47
48 private static final class ScopeState {
49 private final Map<Key<?>, Provider<?>> seeded = new HashMap<>();
50
51 private final Map<Key<?>, Object> provided = new HashMap<>();
52 }
53
54 private final ThreadLocal<LinkedList<ScopeState>> values = new ThreadLocal<>();
55
56 public MojoExecutionScope() {}
57
58 public void enter() {
59 LinkedList<ScopeState> stack = values.get();
60 if (stack == null) {
61 stack = new LinkedList<>();
62 values.set(stack);
63 }
64 stack.addFirst(new ScopeState());
65 }
66
67 private ScopeState getScopeState() {
68 LinkedList<ScopeState> stack = values.get();
69 if (stack == null || stack.isEmpty()) {
70 throw new IllegalStateException();
71 }
72 return stack.getFirst();
73 }
74
75 public void exit() throws MojoExecutionException {
76 final LinkedList<ScopeState> stack = values.get();
77 if (stack == null || stack.isEmpty()) {
78 throw new IllegalStateException();
79 }
80 stack.removeFirst();
81 if (stack.isEmpty()) {
82 values.remove();
83 }
84 }
85
86 public <T> void seed(Class<T> clazz, Provider<T> value) {
87 getScopeState().seeded.put(Key.get(clazz), value);
88 }
89
90 public <T> void seed(Class<T> clazz, final T value) {
91 getScopeState().seeded.put(Key.get(clazz), Providers.of(value));
92 }
93
94 public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
95 return () -> {
96 LinkedList<ScopeState> stack = values.get();
97 if (stack == null || stack.isEmpty()) {
98 throw new OutOfScopeException("Cannot access " + key + " outside of a scoping block");
99 }
100
101 ScopeState state = stack.getFirst();
102
103 Provider<?> seeded = state.seeded.get(key);
104
105 if (seeded != null) {
106 return (T) seeded.get();
107 }
108
109 T provided = (T) state.provided.get(key);
110 if (provided == null && unscoped != null) {
111 provided = unscoped.get();
112 state.provided.put(key, provided);
113 }
114
115 return provided;
116 };
117 }
118
119 @Override
120 public <T> Supplier<T> scope(org.apache.maven.di.Key<T> key, Annotation scope, Supplier<T> unscoped) {
121 Object qualifier = key.getQualifier();
122 Key k = qualifier != null
123 ? Key.get(key.getType(), qualifier instanceof String s ? Names.named(s) : (Annotation) qualifier)
124 : Key.get(key.getType());
125 Provider<T> up = unscoped::get;
126 Provider<T> p = scope(k, up);
127 return p::get;
128 }
129
130 @SuppressWarnings({"unchecked"})
131 public static <T> Provider<T> seededKeyProvider() {
132 return (Provider<T>) SEEDED_KEY_PROVIDER;
133 }
134
135 public void beforeMojoExecution(MojoExecutionEvent event) throws MojoExecutionException {
136 for (WeakMojoExecutionListener provided : getProvidedListeners()) {
137 provided.beforeMojoExecution(event);
138 }
139 }
140
141 public void afterMojoExecutionSuccess(MojoExecutionEvent event) throws MojoExecutionException {
142 for (WeakMojoExecutionListener provided : getProvidedListeners()) {
143 provided.afterMojoExecutionSuccess(event);
144 }
145 }
146
147 public void afterExecutionFailure(MojoExecutionEvent event) {
148 for (WeakMojoExecutionListener provided : getProvidedListeners()) {
149 provided.afterExecutionFailure(event);
150 }
151 }
152
153 private Collection<WeakMojoExecutionListener> getProvidedListeners() {
154
155
156 IdentityHashMap<WeakMojoExecutionListener, Object> listeners = new IdentityHashMap<>();
157 for (Object provided : getScopeState().provided.values()) {
158 if (provided instanceof WeakMojoExecutionListener) {
159 listeners.put((WeakMojoExecutionListener) provided, null);
160 }
161 }
162 return listeners.keySet();
163 }
164 }