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