View Javadoc
1   package org.apache.maven.plugin.testing;
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.io.File;
23  import java.io.InputStream;
24  import java.util.Map;
25  
26  import org.apache.maven.execution.DefaultMavenExecutionRequest;
27  import org.apache.maven.execution.MavenExecutionRequest;
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.internal.MojoExecutionScope;
32  import org.apache.maven.plugin.Mojo;
33  import org.apache.maven.plugin.MojoExecution;
34  import org.apache.maven.project.MavenProject;
35  import org.apache.maven.project.ProjectBuilder;
36  import org.apache.maven.project.ProjectBuildingRequest;
37  import org.apache.maven.session.scope.internal.SessionScope;
38  import org.codehaus.plexus.ContainerConfiguration;
39  import org.codehaus.plexus.PlexusContainer;
40  import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
41  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
42  import org.codehaus.plexus.configuration.PlexusConfiguration;
43  import org.codehaus.plexus.util.xml.Xpp3Dom;
44  import org.eclipse.aether.DefaultRepositorySystemSession;
45  import org.junit.Assert;
46  import org.junit.rules.TestRule;
47  import org.junit.runner.Description;
48  import org.junit.runners.model.Statement;
49  
50  /**
51   * {@link TestRule} for usage with Junit-4.10ff. This is just a wrapper for an embedded 
52   * {@link AbstractMojoTestCase}, so all <tt>protected</tt> methods of the TestCase are 
53   * exhibited as <tt>public</tt> in the rule. You may annotate single tests methods with 
54   * {@link WithoutMojo} to prevent the rule from firing.
55   *
56   * @author Mirko Friedenhagen
57   * @version $Id$
58   * @since 2.2
59   */
60  public class MojoRule
61      implements TestRule
62  {
63      private final AbstractMojoTestCase testCase;
64      
65      public MojoRule() 
66      {
67          this( new AbstractMojoTestCase() {} );
68      }
69  
70      public MojoRule(AbstractMojoTestCase testCase)
71      {
72          this.testCase = testCase;
73      }
74  
75      /**
76       * May be overridden in the implementation to do stuff <em>after</em> the embedded test case 
77       * is set up but <em>before</em> the current test is actually run.
78       *
79       * @throws Throwable
80       */
81      protected void before() throws Throwable
82      {
83          
84      }
85      
86      /**
87       * May be overridden in the implementation to do stuff after the current test was run.
88       */
89      protected void after() 
90      {
91          
92      }
93  
94      public InputStream getPublicDescriptorStream()
95          throws Exception
96      {
97          return testCase.getPublicDescriptorStream();
98      }
99  
100     public String getPluginDescriptorPath()
101     {
102         return testCase.getPluginDescriptorPath();
103     }
104 
105     public String getPluginDescriptorLocation()
106     {
107         return testCase.getPluginDescriptorLocation();
108     }
109 
110     public void setupContainer()
111     {
112         testCase.setupContainer();
113     }
114 
115     public ContainerConfiguration setupContainerConfiguration()
116     {
117         return testCase.setupContainerConfiguration();
118     }
119     
120     public PlexusContainer getContainer()
121     {
122         return testCase.getContainer();
123     }    
124     
125     /**
126      * Lookup the mojo leveraging the subproject pom
127      *
128      * @param goal
129      * @param pluginPom
130      * @return a Mojo instance
131      * @throws Exception
132      */
133     public Mojo lookupMojo( String goal, String pluginPom )
134         throws Exception
135     {
136         return testCase.lookupMojo( goal, pluginPom );
137     }
138 
139     /**
140      * Lookup an empty mojo
141      *
142      * @param goal
143      * @param pluginPom
144      * @return a Mojo instance
145      * @throws Exception
146      */
147     public Mojo lookupEmptyMojo( String goal, String pluginPom )
148         throws Exception
149     {
150         return testCase.lookupEmptyMojo( goal, new File( pluginPom ) );
151     }
152 
153     /**
154      * Lookup the mojo leveraging the actual subprojects pom
155      *
156      * @param goal
157      * @param pom
158      * @return a Mojo instance
159      * @throws Exception
160      */
161     public Mojo lookupMojo( String goal, File pom )
162         throws Exception
163     {
164         return testCase.lookupMojo( goal, pom );
165     }
166 
167     /**
168      * Lookup the mojo leveraging the actual subprojects pom
169      *
170      * @param goal
171      * @param pom
172      * @return a Mojo instance
173      * @throws Exception
174      */
175     public Mojo lookupEmptyMojo( String goal, File pom )
176         throws Exception
177     {
178         return testCase.lookupEmptyMojo( goal, pom );
179     }
180 
181     public Mojo lookupMojo( String groupId, String artifactId, String version, String goal,
182                                PlexusConfiguration pluginConfiguration )
183         throws Exception
184     {
185         return testCase.lookupMojo( groupId, artifactId, version, goal, pluginConfiguration );
186     }
187 
188     public Mojo lookupConfiguredMojo( MavenProject project, String goal )
189         throws Exception
190     {
191         return testCase.lookupConfiguredMojo( project, goal );
192     }
193 
194     public Mojo lookupConfiguredMojo( MavenSession session, MojoExecution execution )
195         throws Exception, ComponentConfigurationException
196     {
197         return testCase.lookupConfiguredMojo( session, execution );
198     }
199 
200     public MavenSession newMavenSession( MavenProject project )
201     {
202         return testCase.newMavenSession( project );
203     }
204 
205     public MojoExecution newMojoExecution( String goal )
206     {
207         return testCase.newMojoExecution( goal );
208     }
209 
210     public PlexusConfiguration extractPluginConfiguration( String artifactId, File pom )
211         throws Exception
212     {
213         return testCase.extractPluginConfiguration( artifactId, pom );
214     }
215 
216     public PlexusConfiguration extractPluginConfiguration( String artifactId, Xpp3Dom pomDom )
217         throws Exception
218     {
219         return testCase.extractPluginConfiguration( artifactId, pomDom );
220     }
221 
222     public Mojo configureMojo( Mojo mojo, String artifactId, File pom )
223         throws Exception
224     {
225         return testCase.configureMojo( mojo, artifactId, pom );
226     }
227 
228     public Mojo configureMojo( Mojo mojo, PlexusConfiguration pluginConfiguration )
229         throws Exception
230     {
231         return testCase.configureMojo( mojo, pluginConfiguration );
232     }
233 
234     /**
235      * Convenience method to obtain the value of a variable on a mojo that might not have a getter.
236      *
237      * NOTE: the caller is responsible for casting to to what the desired type is.
238      *
239      * @param object
240      * @param variable
241      * @return object value of variable
242      * @throws IllegalArgumentException
243      */
244     public Object getVariableValueFromObject( Object object, String variable )
245         throws IllegalAccessException
246     {
247         return testCase.getVariableValueFromObject( object, variable );
248     }
249 
250     /**
251      * Convenience method to obtain all variables and values from the mojo (including its superclasses)
252      *
253      * Note: the values in the map are of type Object so the caller is responsible for casting to desired types.
254      *
255      * @param object
256      * @return map of variable names and values
257      */
258     public Map<String, Object> getVariablesAndValuesFromObject( Object object )
259         throws IllegalAccessException
260     {
261         return testCase.getVariablesAndValuesFromObject( object );
262     }
263 
264     /**
265      * Convenience method to obtain all variables and values from the mojo (including its superclasses)
266      *
267      * Note: the values in the map are of type Object so the caller is responsible for casting to desired types.
268      *
269      * @param clazz
270      * @param object
271      * @return map of variable names and values
272      */
273     public Map<String, Object> getVariablesAndValuesFromObject( Class<?> clazz, Object object )
274         throws IllegalAccessException
275     {
276         return testCase.getVariablesAndValuesFromObject( clazz, object );
277     }
278 
279     /**
280      * Convenience method to set values to variables in objects that don't have setters
281      *
282      * @param object
283      * @param variable
284      * @param value
285      * @throws IllegalAccessException
286      */
287     public void setVariableValueToObject( Object object, String variable, Object value )
288         throws IllegalAccessException
289     {
290         testCase.setVariableValueToObject( object, variable, value );
291     }
292 
293     @Override
294     public Statement apply(final Statement base, Description description) {
295         if (description.getAnnotation(WithoutMojo.class) != null) // skip.
296         {
297             return base;
298         }
299         return new Statement() 
300         {
301             @Override
302             public void evaluate() throws Throwable 
303             {
304                 testCase.setUp();
305                 before();
306                 try 
307                 {
308                     base.evaluate();
309                 } 
310                 finally 
311                 {
312                     after();
313                 }
314             }            
315         };       
316     }
317 
318     /**
319      * @since 3.1.0
320      */
321     public MavenProject readMavenProject( File basedir )
322         throws Exception
323     {
324         File pom = new File( basedir, "pom.xml" );
325         MavenExecutionRequest request = new DefaultMavenExecutionRequest();
326         request.setBaseDirectory( basedir );
327         ProjectBuildingRequest configuration = request.getProjectBuildingRequest();
328         configuration.setRepositorySession( new DefaultRepositorySystemSession() );
329         MavenProject project = lookup( ProjectBuilder.class ).build( pom, configuration ).getProject();
330         Assert.assertNotNull( project );
331         return project;
332     }
333 
334     /**
335      * @since 3.1.0
336      */
337     public void executeMojo( File basedir, String goal )
338         throws Exception
339     {
340         MavenProject project = readMavenProject( basedir );
341         MavenSession session = newMavenSession( project );
342         MojoExecution execution = newMojoExecution( goal );
343         executeMojo( session, project, execution );
344     }
345 
346     /**
347      * @since 3.1.0
348      */
349     public Mojo lookupConfiguredMojo( File basedir, String goal )
350         throws Exception, ComponentConfigurationException
351     {
352         MavenProject project = readMavenProject( basedir );
353         MavenSession session = newMavenSession( project );
354         MojoExecution execution = newMojoExecution( goal );
355         return lookupConfiguredMojo( session, execution );
356     }
357 
358     /**
359      * @since 3.1.0
360      */
361     public final <T> T lookup( final Class<T> role )
362         throws ComponentLookupException
363     {
364         return getContainer().lookup( role );
365     }
366 
367     /**
368      * @since 3.2.0
369      */
370     public void executeMojo( MavenProject project, String goal, Xpp3Dom... parameters )
371         throws Exception
372     {
373         MavenSession session = newMavenSession( project );
374         executeMojo( session, project, goal, parameters );
375     }
376 
377     /**
378      * @since 3.2.0
379      */
380     public void executeMojo( MavenSession session, MavenProject project, String goal, Xpp3Dom... parameters )
381         throws Exception
382     {
383         MojoExecution execution = newMojoExecution( goal );
384         if ( parameters != null )
385         {
386             Xpp3Dom configuration = execution.getConfiguration();
387             for ( Xpp3Dom parameter : parameters )
388             {
389                 configuration.addChild( parameter );
390             }
391         }
392         executeMojo( session, project, execution );
393     }
394 
395     /**
396      * @since 3.2.0
397      */
398     public void executeMojo( MavenSession session, MavenProject project, MojoExecution execution )
399         throws Exception
400     {
401         SessionScope sessionScope = lookup( SessionScope.class );
402         try
403         {
404             sessionScope.enter();
405             sessionScope.seed( MavenSession.class, session );
406 
407             MojoExecutionScope executionScope = lookup( MojoExecutionScope.class );
408             try
409             {
410                 executionScope.enter();
411 
412                 executionScope.seed( MavenProject.class, project );
413                 executionScope.seed( MojoExecution.class, execution );
414 
415                 Mojo mojo = lookupConfiguredMojo( session, execution );
416                 mojo.execute();
417 
418                 MojoExecutionEvent event = new MojoExecutionEvent( session, project, execution, mojo );
419                 for ( MojoExecutionListener listener : getContainer().lookupList( MojoExecutionListener.class ) )
420                 {
421                     listener.afterMojoExecutionSuccess( event );
422                 }
423             }
424             finally
425             {
426                 executionScope.exit();
427             }
428         }
429         finally
430         {
431             sessionScope.exit();
432         }
433     }
434 
435 }