View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugin.testing;
20  
21  import java.io.File;
22  import java.io.InputStream;
23  import java.util.Map;
24  
25  import org.apache.maven.api.plugin.testing.MojoExtension;
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 {@code protected} methods of the TestCase are
53   * exhibited as {@code public} in the rule. You may annotate single tests methods with
54   * {@link WithoutMojo} to prevent the rule from firing.
55   *
56   * @deprecated As of version 3.4.0, it is advised to work with JUnit5 tests which do not
57   * use rules but extensions {@link MojoExtension}
58   * instead.
59   *
60   * @author Mirko Friedenhagen
61   * @since 2.2
62   */
63  @Deprecated
64  public class MojoRule implements TestRule {
65      private final AbstractMojoTestCase testCase;
66  
67      public MojoRule() {
68          this(new AbstractMojoTestCase() {});
69      }
70  
71      public MojoRule(AbstractMojoTestCase testCase) {
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       * May be overridden in the implementation to do stuff after the current test was run.
85       */
86      protected void after() {}
87  
88      public InputStream getPublicDescriptorStream() throws Exception {
89          return testCase.getPublicDescriptorStream();
90      }
91  
92      public String getPluginDescriptorPath() {
93          return testCase.getPluginDescriptorPath();
94      }
95  
96      public String getPluginDescriptorLocation() {
97          return testCase.getPluginDescriptorLocation();
98      }
99  
100     public void setupContainer() {
101         testCase.setupContainer();
102     }
103 
104     public ContainerConfiguration setupContainerConfiguration() {
105         return testCase.setupContainerConfiguration();
106     }
107 
108     public PlexusContainer getContainer() {
109         return testCase.getContainer();
110     }
111 
112     /**
113      * Lookup the mojo leveraging the subproject pom
114      *
115      * @param goal
116      * @param pluginPom
117      * @return a Mojo instance
118      * @throws Exception
119      */
120     public <T extends Mojo> T lookupMojo(String goal, String pluginPom) throws Exception {
121         return testCase.lookupMojo(goal, pluginPom);
122     }
123 
124     /**
125      * Lookup an empty mojo
126      *
127      * @param goal
128      * @param pluginPom
129      * @return a Mojo instance
130      * @throws Exception
131      */
132     public <T extends Mojo> T lookupEmptyMojo(String goal, String pluginPom) throws Exception {
133         return testCase.lookupEmptyMojo(goal, new File(pluginPom));
134     }
135 
136     /**
137      * Lookup the mojo leveraging the actual subprojects pom
138      *
139      * @param goal
140      * @param pom
141      * @return a Mojo instance
142      * @throws Exception
143      */
144     public <T extends Mojo> T lookupMojo(String goal, File pom) throws Exception {
145         return testCase.lookupMojo(goal, pom);
146     }
147 
148     /**
149      * Lookup the mojo leveraging the actual subprojects pom
150      *
151      * @param goal
152      * @param pom
153      * @return a Mojo instance
154      * @throws Exception
155      */
156     public <T extends Mojo> T lookupEmptyMojo(String goal, File pom) throws Exception {
157         return testCase.lookupEmptyMojo(goal, pom);
158     }
159 
160     public <T extends Mojo> T lookupMojo(
161             String groupId, String artifactId, String version, String goal, PlexusConfiguration pluginConfiguration)
162             throws Exception {
163         return testCase.lookupMojo(groupId, artifactId, version, goal, pluginConfiguration);
164     }
165 
166     public <T extends Mojo> T lookupConfiguredMojo(MavenProject project, String goal) throws Exception {
167         return testCase.lookupConfiguredMojo(project, goal);
168     }
169 
170     public <T extends Mojo> T lookupConfiguredMojo(MavenSession session, MojoExecution execution)
171             throws Exception, ComponentConfigurationException {
172         return testCase.lookupConfiguredMojo(session, execution);
173     }
174 
175     public MavenSession newMavenSession(MavenProject project) {
176         return testCase.newMavenSession(project);
177     }
178 
179     public MojoExecution newMojoExecution(String goal) {
180         return testCase.newMojoExecution(goal);
181     }
182 
183     public PlexusConfiguration extractPluginConfiguration(String artifactId, File pom) throws Exception {
184         return testCase.extractPluginConfiguration(artifactId, pom);
185     }
186 
187     public PlexusConfiguration extractPluginConfiguration(String artifactId, Xpp3Dom pomDom) throws Exception {
188         return testCase.extractPluginConfiguration(artifactId, pomDom);
189     }
190 
191     public <T extends Mojo> T configureMojo(T mojo, String artifactId, File pom) throws Exception {
192         return testCase.configureMojo(mojo, artifactId, pom);
193     }
194 
195     public <T extends Mojo> T configureMojo(T mojo, PlexusConfiguration pluginConfiguration) throws Exception {
196         return testCase.configureMojo(mojo, pluginConfiguration);
197     }
198 
199     /**
200      * Convenience method to obtain the value of a variable on a mojo that might not have a getter.
201      *
202      * NOTE: the caller is responsible for casting to to what the desired type is.
203      *
204      * @param object
205      * @param variable
206      * @return object value of variable
207      * @throws IllegalArgumentException
208      */
209     public <T> T getVariableValueFromObject(Object object, String variable) throws IllegalAccessException {
210         return testCase.getVariableValueFromObject(object, variable);
211     }
212 
213     /**
214      * Convenience method to obtain all variables and values from the mojo (including its superclasses)
215      *
216      * Note: the values in the map are of type Object so the caller is responsible for casting to desired types.
217      *
218      * @param object
219      * @return map of variable names and values
220      */
221     public Map<String, Object> getVariablesAndValuesFromObject(Object object) throws IllegalAccessException {
222         return testCase.getVariablesAndValuesFromObject(object);
223     }
224 
225     /**
226      * Convenience method to obtain all variables and values from the mojo (including its superclasses)
227      *
228      * Note: the values in the map are of type Object so the caller is responsible for casting to desired types.
229      *
230      * @param clazz
231      * @param object
232      * @return map of variable names and values
233      */
234     public Map<String, Object> getVariablesAndValuesFromObject(Class<?> clazz, Object object)
235             throws IllegalAccessException {
236         return testCase.getVariablesAndValuesFromObject(clazz, object);
237     }
238 
239     /**
240      * Convenience method to set values to variables in objects that don't have setters
241      *
242      * @param object
243      * @param variable
244      * @param value
245      * @throws IllegalAccessException
246      */
247     public <T> void setVariableValueToObject(Object object, String variable, T value) throws IllegalAccessException {
248         testCase.setVariableValueToObject(object, variable, value);
249     }
250 
251     @Override
252     public Statement apply(final Statement base, Description description) {
253         if (description.getAnnotation(WithoutMojo.class) != null) // skip.
254         {
255             return base;
256         }
257         return new Statement() {
258             @Override
259             public void evaluate() throws Throwable {
260                 testCase.setUp();
261                 before();
262                 try {
263                     base.evaluate();
264                 } finally {
265                     after();
266                 }
267             }
268         };
269     }
270 
271     /**
272      * @since 3.1.0
273      */
274     public MavenProject readMavenProject(File basedir) throws Exception {
275         File pom = new File(basedir, "pom.xml");
276         MavenExecutionRequest request = new DefaultMavenExecutionRequest();
277         request.setBaseDirectory(basedir);
278         ProjectBuildingRequest configuration = request.getProjectBuildingRequest();
279         configuration.setRepositorySession(new DefaultRepositorySystemSession());
280         MavenProject project =
281                 lookup(ProjectBuilder.class).build(pom, configuration).getProject();
282         Assert.assertNotNull(project);
283         return project;
284     }
285 
286     /**
287      * @since 3.1.0
288      */
289     public void executeMojo(File basedir, String goal) throws Exception {
290         MavenProject project = readMavenProject(basedir);
291         MavenSession session = newMavenSession(project);
292         MojoExecution execution = newMojoExecution(goal);
293         executeMojo(session, project, execution);
294     }
295 
296     /**
297      * @since 3.1.0
298      */
299     public <T extends Mojo> T lookupConfiguredMojo(File basedir, String goal)
300             throws Exception, ComponentConfigurationException {
301         MavenProject project = readMavenProject(basedir);
302         MavenSession session = newMavenSession(project);
303         MojoExecution execution = newMojoExecution(goal);
304         return lookupConfiguredMojo(session, execution);
305     }
306 
307     /**
308      * @since 3.1.0
309      */
310     public final <T> T lookup(final Class<T> role) throws ComponentLookupException {
311         return getContainer().lookup(role);
312     }
313 
314     /**
315      * @since 3.2.0
316      */
317     public void executeMojo(MavenProject project, String goal, Xpp3Dom... parameters) throws Exception {
318         MavenSession session = newMavenSession(project);
319         executeMojo(session, project, goal, parameters);
320     }
321 
322     /**
323      * @since 3.2.0
324      */
325     public void executeMojo(MavenSession session, MavenProject project, String goal, Xpp3Dom... parameters)
326             throws Exception {
327         MojoExecution execution = newMojoExecution(goal);
328         if (parameters != null) {
329             Xpp3Dom configuration = execution.getConfiguration();
330             for (Xpp3Dom parameter : parameters) {
331                 configuration.addChild(parameter);
332             }
333         }
334         executeMojo(session, project, execution);
335     }
336 
337     /**
338      * @since 3.2.0
339      */
340     public void executeMojo(MavenSession session, MavenProject project, MojoExecution execution) throws Exception {
341         SessionScope sessionScope = lookup(SessionScope.class);
342         try {
343             sessionScope.enter();
344             sessionScope.seed(MavenSession.class, session);
345 
346             MojoExecutionScope executionScope = lookup(MojoExecutionScope.class);
347             try {
348                 executionScope.enter();
349 
350                 executionScope.seed(MavenProject.class, project);
351                 executionScope.seed(MojoExecution.class, execution);
352 
353                 Mojo mojo = lookupConfiguredMojo(session, execution);
354                 mojo.execute();
355 
356                 MojoExecutionEvent event = new MojoExecutionEvent(session, project, execution, mojo);
357                 for (MojoExecutionListener listener : getContainer().lookupList(MojoExecutionListener.class)) {
358                     listener.afterMojoExecutionSuccess(event);
359                 }
360             } finally {
361                 executionScope.exit();
362             }
363         } finally {
364             sessionScope.exit();
365         }
366     }
367 }