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.IdentityHashMap;
24 import java.util.LinkedList;
25 import java.util.Map;
26
27 import javax.inject.Named;
28 import javax.inject.Singleton;
29
30 import org.apache.maven.execution.MojoExecutionEvent;
31 import org.apache.maven.execution.MojoExecutionListener;
32 import org.apache.maven.execution.scope.MojoExecutionScoped;
33 import org.apache.maven.execution.scope.WeakMojoExecutionListener;
34 import org.apache.maven.plugin.MojoExecution;
35 import org.apache.maven.plugin.MojoExecutionException;
36 import org.apache.maven.project.MavenProject;
37 import org.codehaus.plexus.PlexusContainer;
38 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
39
40 import com.google.common.collect.Maps;
41 import com.google.inject.AbstractModule;
42 import com.google.inject.Key;
43 import com.google.inject.Module;
44 import com.google.inject.OutOfScopeException;
45 import com.google.inject.Provider;
46 import com.google.inject.Scope;
47 import com.google.inject.util.Providers;
48
49 @Named
50 @Singleton
51 public class MojoExecutionScope
52 implements Scope, MojoExecutionListener
53 {
54 private static final Provider<Object> SEEDED_KEY_PROVIDER = new Provider<Object>()
55 {
56 public Object get()
57 {
58 throw new IllegalStateException();
59 }
60 };
61
62 private static final class ScopeState
63 {
64 public final Map<Key<?>, Provider<?>> seeded = Maps.newHashMap();
65
66 public final Map<Key<?>, Object> provided = Maps.newHashMap();
67 }
68
69 private final ThreadLocal<LinkedList<ScopeState>> values = new ThreadLocal<LinkedList<ScopeState>>();
70
71 public MojoExecutionScope()
72 {
73 }
74
75 public void enter()
76 {
77 LinkedList<ScopeState> stack = values.get();
78 if ( stack == null )
79 {
80 stack = new LinkedList<ScopeState>();
81 values.set( stack );
82 }
83 stack.addFirst( new ScopeState() );
84 }
85
86 private ScopeState getScopeState()
87 {
88 LinkedList<ScopeState> stack = values.get();
89 if ( stack == null || stack.isEmpty() )
90 {
91 throw new IllegalStateException();
92 }
93 return stack.getFirst();
94 }
95
96 public void exit()
97 throws MojoExecutionException
98 {
99 final LinkedList<ScopeState> stack = values.get();
100 if ( stack == null || stack.isEmpty() )
101 {
102 throw new IllegalStateException();
103 }
104 stack.removeFirst();
105 if ( stack.isEmpty() )
106 {
107 values.remove();
108 }
109 }
110
111 public <T> void seed( Class<T> clazz, Provider<T> value )
112 {
113 getScopeState().seeded.put( Key.get( clazz ), value );
114 }
115
116 public <T> void seed( Class<T> clazz, final T value )
117 {
118 getScopeState().seeded.put( Key.get( clazz ), Providers.of( value ) );
119 }
120
121 public <T> Provider<T> scope( final Key<T> key, final Provider<T> unscoped )
122 {
123 return new Provider<T>()
124 {
125 @SuppressWarnings( "unchecked" )
126 public T get()
127 {
128 LinkedList<ScopeState> stack = values.get();
129 if ( stack == null || stack.isEmpty() )
130 {
131 throw new OutOfScopeException( "Cannot access " + key + " outside of a scoping block" );
132 }
133
134 ScopeState state = stack.getFirst();
135
136 Provider<?> seeded = state.seeded.get( key );
137
138 if ( seeded != null )
139 {
140 return (T) seeded.get();
141 }
142
143 T provided = (T) state.provided.get( key );
144 if ( provided == null && unscoped != null )
145 {
146 provided = unscoped.get();
147 state.provided.put( key, provided );
148 }
149
150 return provided;
151 }
152 };
153 }
154
155 @SuppressWarnings( { "unchecked" } )
156 public static <T> Provider<T> seededKeyProvider()
157 {
158 return (Provider<T>) SEEDED_KEY_PROVIDER;
159 }
160
161 public static Module getScopeModule( PlexusContainer container )
162 throws ComponentLookupException
163 {
164 final MojoExecutionScope scope = container.lookup( MojoExecutionScope.class );
165 return new AbstractModule()
166 {
167 @Override
168 protected void configure()
169 {
170 bindScope( MojoExecutionScoped.class, scope );
171
172
173 bind( MavenProject.class ).toProvider( MojoExecutionScope.<MavenProject> seededKeyProvider() ).in( scope );
174 bind( MojoExecution.class ).toProvider( MojoExecutionScope.<MojoExecution> seededKeyProvider() ).in( scope );
175 }
176 };
177 }
178
179 public void beforeMojoExecution( MojoExecutionEvent event )
180 throws MojoExecutionException
181 {
182 for ( WeakMojoExecutionListener provided : getProvidedListeners() )
183 {
184 provided.beforeMojoExecution( event );
185 }
186 }
187
188 public void afterMojoExecutionSuccess( MojoExecutionEvent event )
189 throws MojoExecutionException
190 {
191 for ( WeakMojoExecutionListener provided : getProvidedListeners() )
192 {
193 provided.afterMojoExecutionSuccess( event );
194 }
195 }
196
197 public void afterExecutionFailure( MojoExecutionEvent event )
198 {
199 for ( WeakMojoExecutionListener provided : getProvidedListeners() )
200 {
201 provided.afterExecutionFailure( event );
202 }
203 }
204
205 private Collection<WeakMojoExecutionListener> getProvidedListeners()
206 {
207
208
209 IdentityHashMap<WeakMojoExecutionListener, Object> listeners =
210 new IdentityHashMap<WeakMojoExecutionListener, Object>();
211 for ( Object provided : getScopeState().provided.values() )
212 {
213 if ( provided instanceof WeakMojoExecutionListener )
214 {
215 listeners.put( (WeakMojoExecutionListener) provided, null );
216 }
217 }
218 return listeners.keySet();
219 }
220 }