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