View Javadoc
1   package org.apache.maven.execution.scope.internal;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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                 // standard scope bindings
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 }