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;
20  
21  import javax.inject.Inject;
22  
23  import java.io.File;
24  import java.lang.reflect.InvocationTargetException;
25  import java.nio.file.Path;
26  import java.nio.file.Paths;
27  import java.util.ArrayList;
28  import java.util.Collections;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.Properties;
32  
33  import org.apache.maven.AbstractCoreMavenComponentTestCase;
34  import org.apache.maven.artifact.Artifact;
35  import org.apache.maven.artifact.ArtifactUtils;
36  import org.apache.maven.artifact.repository.ArtifactRepository;
37  import org.apache.maven.bridge.MavenRepositorySystem;
38  import org.apache.maven.execution.DefaultMavenExecutionRequest;
39  import org.apache.maven.execution.DefaultMavenExecutionResult;
40  import org.apache.maven.execution.MavenExecutionRequest;
41  import org.apache.maven.execution.MavenSession;
42  import org.apache.maven.model.Build;
43  import org.apache.maven.model.Dependency;
44  import org.apache.maven.model.Model;
45  import org.apache.maven.model.root.RootLocator;
46  import org.apache.maven.plugin.descriptor.MojoDescriptor;
47  import org.apache.maven.plugin.descriptor.PluginDescriptor;
48  import org.apache.maven.project.DuplicateProjectException;
49  import org.apache.maven.project.MavenProject;
50  import org.codehaus.plexus.MutablePlexusContainer;
51  import org.codehaus.plexus.PlexusContainer;
52  import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
53  import org.codehaus.plexus.util.dag.CycleDetectedException;
54  import org.junit.jupiter.api.Test;
55  
56  import static org.codehaus.plexus.testing.PlexusExtension.getTestFile;
57  import static org.junit.jupiter.api.Assertions.assertEquals;
58  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
59  import static org.junit.jupiter.api.Assertions.assertNotNull;
60  import static org.junit.jupiter.api.Assertions.assertNull;
61  import static org.junit.jupiter.api.Assertions.assertSame;
62  import static org.junit.jupiter.api.Assertions.assertThrows;
63  import static org.junit.jupiter.api.Assertions.assertTrue;
64  
65  /**
66   * @author Jason van Zyl
67   */
68  class PluginParameterExpressionEvaluatorTest extends AbstractCoreMavenComponentTestCase {
69      private static final String FS = File.separator;
70  
71      @Inject
72      private MavenRepositorySystem factory;
73  
74      private Path rootDirectory;
75  
76      @Test
77      void testPluginDescriptorExpressionReference() throws Exception {
78          MojoExecution exec = newMojoExecution();
79  
80          MavenSession session = newMavenSession();
81  
82          Object result = new PluginParameterExpressionEvaluator(session, exec).evaluate("${plugin}");
83  
84          System.out.println("Result: " + result);
85  
86          assertSame(
87                  exec.getMojoDescriptor().getPluginDescriptor(),
88                  result,
89                  "${plugin} expression does not return plugin descriptor.");
90      }
91  
92      @Test
93      void testPluginArtifactsExpressionReference() throws Exception {
94          MojoExecution exec = newMojoExecution();
95  
96          Artifact depArtifact = createArtifact("group", "artifact", "1");
97  
98          List<Artifact> deps = new ArrayList<>();
99          deps.add(depArtifact);
100 
101         exec.getMojoDescriptor().getPluginDescriptor().setArtifacts(deps);
102 
103         MavenSession session = newMavenSession();
104 
105         @SuppressWarnings("unchecked")
106         List<Artifact> depResults =
107                 (List<Artifact>) new PluginParameterExpressionEvaluator(session, exec).evaluate("${plugin.artifacts}");
108 
109         System.out.println("Result: " + depResults);
110 
111         assertNotNull(depResults);
112         assertEquals(1, depResults.size());
113         assertSame(depArtifact, depResults.get(0), "dependency artifact is wrong.");
114     }
115 
116     @Test
117     void testPluginArtifactMapExpressionReference() throws Exception {
118         MojoExecution exec = newMojoExecution();
119 
120         Artifact depArtifact = createArtifact("group", "artifact", "1");
121 
122         List<Artifact> deps = new ArrayList<>();
123         deps.add(depArtifact);
124 
125         exec.getMojoDescriptor().getPluginDescriptor().setArtifacts(deps);
126 
127         MavenSession session = newMavenSession();
128 
129         @SuppressWarnings("unchecked")
130         Map<String, Artifact> depResults = (Map<String, Artifact>)
131                 new PluginParameterExpressionEvaluator(session, exec).evaluate("${plugin.artifactMap}");
132 
133         System.out.println("Result: " + depResults);
134 
135         assertNotNull(depResults);
136         assertEquals(1, depResults.size());
137         assertSame(
138                 depArtifact,
139                 depResults.get(ArtifactUtils.versionlessKey(depArtifact)),
140                 "dependency artifact is wrong.");
141     }
142 
143     @Test
144     void testPluginArtifactIdExpressionReference() throws Exception {
145         MojoExecution exec = newMojoExecution();
146 
147         MavenSession session = newMavenSession();
148 
149         Object result = new PluginParameterExpressionEvaluator(session, exec).evaluate("${plugin.artifactId}");
150 
151         System.out.println("Result: " + result);
152 
153         assertSame(
154                 exec.getMojoDescriptor().getPluginDescriptor().getArtifactId(),
155                 result,
156                 "${plugin.artifactId} expression does not return plugin descriptor's artifactId.");
157     }
158 
159     @Test
160     void testValueExtractionWithAPomValueContainingAPath() throws Exception {
161         String expected = getTestFile("target/test-classes/target/classes").getCanonicalPath();
162 
163         Build build = new Build();
164         build.setDirectory(expected.substring(0, expected.length() - "/classes".length()));
165 
166         Model model = new Model();
167         model.setBuild(build);
168 
169         MavenProject project = new MavenProject(model);
170         project.setFile(new File("pom.xml").getCanonicalFile());
171 
172         ExpressionEvaluator expressionEvaluator = createExpressionEvaluator(project, null, new Properties());
173 
174         Object value = expressionEvaluator.evaluate("${project.build.directory}/classes");
175         String actual = new File(value.toString()).getCanonicalPath();
176 
177         assertEquals(expected, actual);
178     }
179 
180     @Test
181     void testEscapedVariablePassthrough() throws Exception {
182         String var = "${var}";
183 
184         Model model = new Model();
185         model.setVersion("1");
186 
187         MavenProject project = new MavenProject(model);
188 
189         ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
190 
191         Object value = ee.evaluate("$" + var);
192 
193         assertEquals(var, value);
194     }
195 
196     @Test
197     void testEscapedVariablePassthroughInLargerExpression() throws Exception {
198         String var = "${var}";
199         String key = var + " with version: ${project.version}";
200 
201         Model model = new Model();
202         model.setVersion("1");
203 
204         MavenProject project = new MavenProject(model);
205 
206         ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
207 
208         Object value = ee.evaluate("$" + key);
209 
210         assertEquals("${var} with version: 1", value);
211     }
212 
213     @Test
214     void testMultipleSubExpressionsInLargerExpression() throws Exception {
215         String key = "${project.artifactId} with version: ${project.version}";
216 
217         Model model = new Model();
218         model.setArtifactId("test");
219         model.setVersion("1");
220 
221         MavenProject project = new MavenProject(model);
222 
223         ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
224 
225         Object value = ee.evaluate(key);
226 
227         assertEquals("test with version: 1", value);
228     }
229 
230     @Test
231     void testMissingPOMPropertyRefInLargerExpression() throws Exception {
232         String expr = "/path/to/someproject-${baseVersion}";
233 
234         MavenProject project = new MavenProject(new Model());
235 
236         ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
237 
238         Object value = ee.evaluate(expr);
239 
240         assertEquals(expr, value);
241     }
242 
243     @Test
244     void testPOMPropertyExtractionWithMissingProject_WithDotNotation() throws Exception {
245         String key = "m2.name";
246         String checkValue = "value";
247 
248         Properties properties = new Properties();
249         properties.setProperty(key, checkValue);
250 
251         Model model = new Model();
252         model.setProperties(properties);
253 
254         MavenProject project = new MavenProject(model);
255 
256         ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
257 
258         Object value = ee.evaluate("${" + key + "}");
259 
260         assertEquals(checkValue, value);
261     }
262 
263     @Test
264     void testBasedirExtractionWithMissingProject() throws Exception {
265         ExpressionEvaluator ee = createExpressionEvaluator(null, null, new Properties());
266 
267         Object value = ee.evaluate("${basedir}");
268 
269         assertEquals(System.getProperty("user.dir"), value);
270     }
271 
272     @Test
273     void testValueExtractionFromSystemPropertiesWithMissingProject() throws Exception {
274         String sysprop = "PPEET_sysprop1";
275 
276         Properties executionProperties = new Properties();
277 
278         if (executionProperties.getProperty(sysprop) == null) {
279             executionProperties.setProperty(sysprop, "value");
280         }
281 
282         ExpressionEvaluator ee = createExpressionEvaluator(null, null, executionProperties);
283 
284         Object value = ee.evaluate("${" + sysprop + "}");
285 
286         assertEquals("value", value);
287     }
288 
289     @Test
290     void testValueExtractionFromSystemPropertiesWithMissingProject_WithDotNotation() throws Exception {
291         String sysprop = "PPEET.sysprop2";
292 
293         Properties executionProperties = new Properties();
294 
295         if (executionProperties.getProperty(sysprop) == null) {
296             executionProperties.setProperty(sysprop, "value");
297         }
298 
299         ExpressionEvaluator ee = createExpressionEvaluator(null, null, executionProperties);
300 
301         Object value = ee.evaluate("${" + sysprop + "}");
302 
303         assertEquals("value", value);
304     }
305 
306     @SuppressWarnings("deprecation")
307     private static MavenSession createSession(PlexusContainer container, ArtifactRepository repo, Properties properties)
308             throws CycleDetectedException, DuplicateProjectException {
309         MavenExecutionRequest request = new DefaultMavenExecutionRequest()
310                 .setSystemProperties(properties)
311                 .setGoals(Collections.<String>emptyList())
312                 .setBaseDirectory(new File(""))
313                 .setLocalRepository(repo);
314 
315         return new MavenSession(
316                 container, request, new DefaultMavenExecutionResult(), Collections.<MavenProject>emptyList());
317     }
318 
319     @Test
320     void testLocalRepositoryExtraction() throws Exception {
321         ExpressionEvaluator expressionEvaluator =
322                 createExpressionEvaluator(createDefaultProject(), null, new Properties());
323         Object value = expressionEvaluator.evaluate("${localRepository}");
324 
325         assertEquals("local", ((ArtifactRepository) value).getId());
326     }
327 
328     @Test
329     void testTwoExpressions() throws Exception {
330         Build build = new Build();
331         build.setDirectory("expected-directory");
332         build.setFinalName("expected-finalName");
333 
334         Model model = new Model();
335         model.setBuild(build);
336 
337         ExpressionEvaluator expressionEvaluator =
338                 createExpressionEvaluator(new MavenProject(model), null, new Properties());
339 
340         Object value = expressionEvaluator.evaluate("${project.build.directory}" + FS + "${project.build.finalName}");
341 
342         assertEquals("expected-directory" + File.separatorChar + "expected-finalName", value);
343     }
344 
345     @Test
346     void testShouldExtractPluginArtifacts() throws Exception {
347         PluginDescriptor pd = new PluginDescriptor();
348 
349         Artifact artifact = createArtifact("testGroup", "testArtifact", "1.0");
350 
351         pd.setArtifacts(Collections.singletonList(artifact));
352 
353         ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), pd, new Properties());
354 
355         Object value = ee.evaluate("${plugin.artifacts}");
356 
357         assertTrue(value instanceof List);
358 
359         @SuppressWarnings("unchecked")
360         List<Artifact> artifacts = (List<Artifact>) value;
361 
362         assertEquals(1, artifacts.size());
363 
364         Artifact result = artifacts.get(0);
365 
366         assertEquals("testGroup", result.getGroupId());
367     }
368 
369     @Test
370     void testRootDirectoryNotPrefixed() throws Exception {
371         ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), null, new Properties());
372         assertNull(ee.evaluate("${rootDirectory}"));
373     }
374 
375     @Test
376     void testRootDirectoryWithNull() throws Exception {
377         ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), null, new Properties());
378         Exception e = assertThrows(Exception.class, () -> ee.evaluate("${session.rootDirectory}"));
379         e = assertInstanceOf(InvocationTargetException.class, e.getCause());
380         e = assertInstanceOf(IllegalStateException.class, e.getCause());
381         assertEquals(RootLocator.UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE, e.getMessage());
382     }
383 
384     @Test
385     void testRootDirectory() throws Exception {
386         this.rootDirectory = Paths.get("myRootDirectory");
387         ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), null, new Properties());
388         assertInstanceOf(Path.class, ee.evaluate("${session.rootDirectory}"));
389     }
390 
391     private MavenProject createDefaultProject() {
392         return new MavenProject(new Model());
393     }
394 
395     private ExpressionEvaluator createExpressionEvaluator(
396             MavenProject project, PluginDescriptor pluginDescriptor, Properties executionProperties) throws Exception {
397         ArtifactRepository repo = getLocalRepository();
398 
399         MutablePlexusContainer container = (MutablePlexusContainer) getContainer();
400         MavenSession session = createSession(container, repo, executionProperties);
401         session.setCurrentProject(project);
402         session.getRequest().setRootDirectory(rootDirectory);
403 
404         MojoDescriptor mojo = new MojoDescriptor();
405         mojo.setPluginDescriptor(pluginDescriptor);
406         mojo.setGoal("goal");
407 
408         MojoExecution mojoExecution = new MojoExecution(mojo);
409 
410         return new PluginParameterExpressionEvaluator(session, mojoExecution);
411     }
412 
413     protected Artifact createArtifact(String groupId, String artifactId, String version) throws Exception {
414         Dependency dependency = new Dependency();
415         dependency.setGroupId(groupId);
416         dependency.setArtifactId(artifactId);
417         dependency.setVersion(version);
418         dependency.setType("jar");
419         dependency.setScope("compile");
420 
421         return factory.createDependencyArtifact(dependency);
422     }
423 
424     private MojoExecution newMojoExecution() {
425         PluginDescriptor pd = new PluginDescriptor();
426         pd.setArtifactId("my-plugin");
427         pd.setGroupId("org.myco.plugins");
428         pd.setVersion("1");
429 
430         MojoDescriptor md = new MojoDescriptor();
431         md.setPluginDescriptor(pd);
432 
433         pd.addComponentDescriptor(md);
434 
435         return new MojoExecution(md);
436     }
437 
438     private MavenSession newMavenSession() throws Exception {
439         return createMavenSession(null);
440     }
441 
442     @Override
443     protected String getProjectsDirectory() {
444         // TODO Auto-generated method stub
445         return null;
446     }
447 }