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