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