1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugin;
20
21 import javax.inject.Inject;
22
23 import java.io.File;
24 import java.net.URI;
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.Objects;
32 import java.util.Properties;
33
34 import org.apache.maven.AbstractCoreMavenComponentTestCase;
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.configuration.internal.EnhancedComponentConfigurator;
40 import org.apache.maven.execution.DefaultMavenExecutionRequest;
41 import org.apache.maven.execution.DefaultMavenExecutionResult;
42 import org.apache.maven.execution.MavenExecutionRequest;
43 import org.apache.maven.execution.MavenSession;
44 import org.apache.maven.impl.model.reflection.IntrospectionException;
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.CycleDetectedException;
52 import org.apache.maven.project.DuplicateProjectException;
53 import org.apache.maven.project.MavenProject;
54 import org.codehaus.plexus.MutablePlexusContainer;
55 import org.codehaus.plexus.PlexusContainer;
56 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
57 import org.codehaus.plexus.configuration.DefaultPlexusConfiguration;
58 import org.codehaus.plexus.util.Os;
59 import org.junit.jupiter.api.Test;
60 import org.junit.jupiter.params.ParameterizedTest;
61 import org.junit.jupiter.params.provider.ValueSource;
62
63 import static org.codehaus.plexus.testing.PlexusExtension.getTestFile;
64 import static org.junit.jupiter.api.Assertions.assertEquals;
65 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
66 import static org.junit.jupiter.api.Assertions.assertNotNull;
67 import static org.junit.jupiter.api.Assertions.assertNull;
68 import static org.junit.jupiter.api.Assertions.assertSame;
69 import static org.junit.jupiter.api.Assertions.assertThrows;
70
71
72
73 class PluginParameterExpressionEvaluatorTest extends AbstractCoreMavenComponentTestCase {
74 private static final String FS = File.separator;
75
76 @Inject
77 private MavenRepositorySystem factory;
78
79 private Path rootDirectory;
80
81 @Test
82 void testPluginDescriptorExpressionReference() throws Exception {
83 MojoExecution exec = newMojoExecution();
84
85 MavenSession session = newMavenSession();
86
87 Object result = new PluginParameterExpressionEvaluator(session, exec).evaluate("${plugin}");
88
89 System.out.println("Result: " + result);
90
91 assertSame(
92 exec.getMojoDescriptor().getPluginDescriptor(),
93 result,
94 "${plugin} expression does not return plugin descriptor.");
95 }
96
97 @Test
98 void testPluginArtifactsExpressionReference() throws Exception {
99 MojoExecution exec = newMojoExecution();
100
101 Artifact depArtifact = createArtifact("group", "artifact", "1");
102
103 List<Artifact> deps = new ArrayList<>();
104 deps.add(depArtifact);
105
106 exec.getMojoDescriptor().getPluginDescriptor().setArtifacts(deps);
107
108 MavenSession session = newMavenSession();
109
110 @SuppressWarnings("unchecked")
111 List<Artifact> depResults =
112 (List<Artifact>) new PluginParameterExpressionEvaluator(session, exec).evaluate("${plugin.artifacts}");
113
114 System.out.println("Result: " + depResults);
115
116 assertNotNull(depResults);
117 assertEquals(1, depResults.size());
118 assertSame(depArtifact, depResults.get(0), "dependency artifact is wrong.");
119 }
120
121 @Test
122 void testPluginArtifactMapExpressionReference() throws Exception {
123 MojoExecution exec = newMojoExecution();
124
125 Artifact depArtifact = createArtifact("group", "artifact", "1");
126
127 List<Artifact> deps = new ArrayList<>();
128 deps.add(depArtifact);
129
130 exec.getMojoDescriptor().getPluginDescriptor().setArtifacts(deps);
131
132 MavenSession session = newMavenSession();
133
134 @SuppressWarnings("unchecked")
135 Map<String, Artifact> depResults = (Map<String, Artifact>)
136 new PluginParameterExpressionEvaluator(session, exec).evaluate("${plugin.artifactMap}");
137
138 System.out.println("Result: " + depResults);
139
140 assertNotNull(depResults);
141 assertEquals(1, depResults.size());
142 assertSame(
143 depArtifact,
144 depResults.get(ArtifactUtils.versionlessKey(depArtifact)),
145 "dependency artifact is wrong.");
146 }
147
148 @Test
149 void testPluginArtifactIdExpressionReference() throws Exception {
150 MojoExecution exec = newMojoExecution();
151
152 MavenSession session = newMavenSession();
153
154 Object result = new PluginParameterExpressionEvaluator(session, exec).evaluate("${plugin.artifactId}");
155
156 System.out.println("Result: " + result);
157
158 assertSame(
159 exec.getMojoDescriptor().getPluginDescriptor().getArtifactId(),
160 result,
161 "${plugin.artifactId} expression does not return plugin descriptor's artifactId.");
162 }
163
164 @Test
165 void testValueExtractionWithAPomValueContainingAPath() throws Exception {
166 String expected = getTestFile("target/test-classes/target/classes").getCanonicalPath();
167
168 Build build = new Build();
169 build.setDirectory(expected.substring(0, expected.length() - "/classes".length()));
170
171 Model model = new Model();
172 model.setBuild(build);
173
174 MavenProject project = new MavenProject(model);
175 project.setFile(new File("pom.xml").getCanonicalFile());
176
177 ExpressionEvaluator expressionEvaluator = createExpressionEvaluator(project, null, new Properties());
178
179 Object value = expressionEvaluator.evaluate("${project.build.directory}/classes");
180 String actual = new File(value.toString()).getCanonicalPath();
181
182 assertEquals(expected, actual);
183 }
184
185 @Test
186 void testEscapedVariablePassthrough() throws Exception {
187 String var = "${var}";
188
189 Model model = new Model();
190 model.setVersion("1");
191
192 MavenProject project = new MavenProject(model);
193
194 ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
195
196 Object value = ee.evaluate("$" + var);
197
198 assertEquals(var, value);
199 }
200
201 @Test
202 void testEscapedVariablePassthroughInLargerExpression() throws Exception {
203 String var = "${var}";
204 String key = var + " with version: ${project.version}";
205
206 Model model = new Model();
207 model.setVersion("1");
208
209 MavenProject project = new MavenProject(model);
210
211 ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
212
213 Object value = ee.evaluate("$" + key);
214
215 assertEquals("${var} with version: 1", value);
216 }
217
218 @Test
219 void testMultipleSubExpressionsInLargerExpression() throws Exception {
220 String key = "${project.artifactId} with version: ${project.version}";
221
222 Model model = new Model();
223 model.setArtifactId("test");
224 model.setVersion("1");
225
226 MavenProject project = new MavenProject(model);
227
228 ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
229
230 Object value = ee.evaluate(key);
231
232 assertEquals("test with version: 1", value);
233 }
234
235 @Test
236 void testMissingPOMPropertyRefInLargerExpression() throws Exception {
237 String expr = "/path/to/someproject-${baseVersion}";
238
239 MavenProject project = new MavenProject(new Model());
240
241 ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
242
243 Object value = ee.evaluate(expr);
244
245 assertEquals(expr, value);
246 }
247
248 @Test
249 void testPOMPropertyExtractionWithMissingProjectWithDotNotation() throws Exception {
250 String key = "m2.name";
251 String checkValue = "value";
252
253 Properties properties = new Properties();
254 properties.setProperty(key, checkValue);
255
256 Model model = new Model();
257 model.setProperties(properties);
258
259 MavenProject project = new MavenProject(model);
260
261 ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
262
263 Object value = ee.evaluate("${" + key + "}");
264
265 assertEquals(checkValue, value);
266 }
267
268 @Test
269 void testBasedirExtractionWithMissingProject() throws Exception {
270 ExpressionEvaluator ee = createExpressionEvaluator(null, null, new Properties());
271
272 Object value = ee.evaluate("${basedir}");
273
274 assertEquals(System.getProperty("user.dir"), value);
275 }
276
277 @Test
278 void testValueExtractionFromSystemPropertiesWithMissingProject() throws Exception {
279 String sysprop = "PPEET_sysprop1";
280
281 Properties executionProperties = new Properties();
282
283 if (executionProperties.getProperty(sysprop) == null) {
284 executionProperties.setProperty(sysprop, "value");
285 }
286
287 ExpressionEvaluator ee = createExpressionEvaluator(null, null, executionProperties);
288
289 Object value = ee.evaluate("${" + sysprop + "}");
290
291 assertEquals("value", value);
292 }
293
294 @ParameterizedTest
295 @ValueSource(
296 strings = {
297 "prefix-${PPEET_nonexisting_ps_property}",
298 "${PPEET_nonexisting_ps_property}-suffix",
299 "prefix-${PPEET_nonexisting_ps_property}-suffix",
300 })
301 void testValueExtractionOfMissingPrefixedSuffixedProperty(String missingPropertyExpression) throws Exception {
302 Properties executionProperties = new Properties();
303
304 ExpressionEvaluator ee = createExpressionEvaluator(null, null, executionProperties);
305
306 Object value = ee.evaluate(missingPropertyExpression);
307
308 assertEquals(missingPropertyExpression, value);
309 }
310
311 @Test
312 void testValueExtractionOfMissingProperty() throws Exception {
313 Properties executionProperties = new Properties();
314
315 ExpressionEvaluator ee = createExpressionEvaluator(null, null, executionProperties);
316
317 Object value = ee.evaluate("${PPEET_nonexisting_property}");
318
319 assertNull(value);
320 }
321
322 @Test
323 void testValueExtractionFromSystemPropertiesWithMissingProjectWithDotNotation() throws Exception {
324 String sysprop = "PPEET.sysprop2";
325
326 Properties executionProperties = new Properties();
327
328 if (executionProperties.getProperty(sysprop) == null) {
329 executionProperties.setProperty(sysprop, "value");
330 }
331
332 ExpressionEvaluator ee = createExpressionEvaluator(null, null, executionProperties);
333
334 Object value = ee.evaluate("${" + sysprop + "}");
335
336 assertEquals("value", value);
337 }
338
339 @SuppressWarnings("deprecation")
340 private static MavenSession createSession(PlexusContainer container, ArtifactRepository repo, Properties properties)
341 throws CycleDetectedException, DuplicateProjectException {
342 MavenExecutionRequest request = new DefaultMavenExecutionRequest()
343 .setSystemProperties(properties)
344 .setGoals(Collections.emptyList())
345 .setBaseDirectory(new File(""))
346 .setLocalRepository(repo);
347
348 return new MavenSession(container, request, new DefaultMavenExecutionResult(), Collections.emptyList());
349 }
350
351 @Test
352 void testLocalRepositoryExtraction() throws Exception {
353 ExpressionEvaluator expressionEvaluator =
354 createExpressionEvaluator(createDefaultProject(), null, new Properties());
355 Object value = expressionEvaluator.evaluate("${localRepository}");
356
357 assertEquals("local", ((ArtifactRepository) value).getId());
358 }
359
360 @Test
361 void testTwoExpressions() throws Exception {
362 Build build = new Build();
363 build.setDirectory("expected-directory");
364 build.setFinalName("expected-finalName");
365
366 Model model = new Model();
367 model.setBuild(build);
368
369 ExpressionEvaluator expressionEvaluator =
370 createExpressionEvaluator(new MavenProject(model), null, new Properties());
371
372 Object value = expressionEvaluator.evaluate("${project.build.directory}" + FS + "${project.build.finalName}");
373
374 assertEquals("expected-directory" + File.separatorChar + "expected-finalName", value);
375 }
376
377 @Test
378 void testShouldExtractPluginArtifacts() throws Exception {
379 PluginDescriptor pd = new PluginDescriptor();
380
381 Artifact artifact = createArtifact("testGroup", "testArtifact", "1.0");
382
383 pd.setArtifacts(Collections.singletonList(artifact));
384
385 ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), pd, new Properties());
386
387 Object value = ee.evaluate("${plugin.artifacts}");
388
389 assertInstanceOf(List.class, value);
390
391 @SuppressWarnings("unchecked")
392 List<Artifact> artifacts = (List<Artifact>) value;
393
394 assertEquals(1, artifacts.size());
395
396 Artifact result = artifacts.get(0);
397
398 assertEquals("testGroup", result.getGroupId());
399 }
400
401 @Test
402 void testRootDirectoryNotPrefixed() throws Exception {
403 ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), null, new Properties());
404 assertNull(ee.evaluate("${rootDirectory}"));
405 }
406
407 @Test
408 void testRootDirectoryWithNull() throws Exception {
409 ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), null, new Properties());
410 Exception e = assertThrows(Exception.class, () -> ee.evaluate("${session.rootDirectory}"));
411 e = assertInstanceOf(IntrospectionException.class, e.getCause());
412 e = assertInstanceOf(IllegalStateException.class, e.getCause());
413 assertEquals(RootLocator.UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE, e.getMessage());
414 }
415
416 @Test
417 void testRootDirectory() throws Exception {
418 this.rootDirectory = Paths.get("myRootDirectory");
419 ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), null, new Properties());
420 assertInstanceOf(Path.class, ee.evaluate("${session.rootDirectory}"));
421 }
422
423 @Test
424 public void testUri() throws Exception {
425 Path path = Paths.get("").toAbsolutePath();
426
427 MavenSession mavenSession = createMavenSession(null);
428 mavenSession.getRequest().setTopDirectory(path);
429 mavenSession.getRequest().setRootDirectory(path);
430
431 Object result = new PluginParameterExpressionEvaluator(mavenSession, new MojoExecution(null))
432 .evaluate("${session.rootDirectory.uri}");
433 assertEquals(path.toUri(), result);
434 }
435
436 @Test
437 public void testPath() throws Exception {
438 Path path = Paths.get("").toAbsolutePath();
439
440 MavenSession mavenSession = createMavenSession(null);
441 mavenSession.getRequest().setTopDirectory(path);
442 mavenSession.getRequest().setRootDirectory(path);
443
444 Object result = new PluginParameterExpressionEvaluator(mavenSession, new MojoExecution(null))
445 .evaluate("${session.rootDirectory/target}");
446 assertEquals(path.resolve("target"), result);
447 }
448
449 @Test
450 public void testPluginInjection() throws Exception {
451 Path path = Paths.get("rép➜α").toAbsolutePath();
452
453 MavenSession mavenSession = createMavenSession(null);
454 mavenSession.getRequest().setTopDirectory(path);
455 mavenSession.getRequest().setRootDirectory(path);
456
457 PluginParameterExpressionEvaluator evaluator =
458 new PluginParameterExpressionEvaluator(mavenSession, new MojoExecution(null));
459
460 DefaultPlexusConfiguration configuration = new DefaultPlexusConfiguration("config");
461 configuration.addChild("uri", "${session.rootDirectory.uri}");
462 configuration.addChild("path", "${session.rootDirectory}");
463 configuration.addChild("uriString", "${session.rootDirectory.uri.string}");
464 configuration.addChild("uriAsciiString", "${session.rootDirectory.uri.ASCIIString}");
465 configuration.addChild("pathString", "${session.rootDirectory.string}");
466
467 Mojo mojo = new Mojo();
468 new EnhancedComponentConfigurator().configureComponent(mojo, configuration, evaluator, null);
469
470 assertEquals(
471 Objects.equals(path.toUri().toString(), path.toUri().toASCIIString()), !Os.isFamily(Os.FAMILY_WINDOWS));
472 assertEquals(mojo.uri, path.toUri());
473 assertEquals(mojo.path, path);
474 assertEquals(mojo.uriString, path.toUri().toString());
475 assertEquals(mojo.uriAsciiString, path.toUri().toASCIIString());
476 assertEquals(mojo.pathString, path.toString());
477 }
478
479 private MavenProject createDefaultProject() {
480 return new MavenProject(new Model());
481 }
482
483 private ExpressionEvaluator createExpressionEvaluator(
484 MavenProject project, PluginDescriptor pluginDescriptor, Properties executionProperties) throws Exception {
485 ArtifactRepository repo = getLocalRepository();
486
487 MutablePlexusContainer container = (MutablePlexusContainer) getContainer();
488 MavenSession session = createSession(container, repo, executionProperties);
489 session.setCurrentProject(project);
490 session.getRequest().setRootDirectory(rootDirectory);
491
492 MojoDescriptor mojo = new MojoDescriptor();
493 mojo.setPluginDescriptor(pluginDescriptor);
494 mojo.setGoal("goal");
495
496 MojoExecution mojoExecution = new MojoExecution(mojo);
497
498 return new PluginParameterExpressionEvaluator(session, mojoExecution);
499 }
500
501 protected Artifact createArtifact(String groupId, String artifactId, String version) throws Exception {
502 Dependency dependency = new Dependency();
503 dependency.setGroupId(groupId);
504 dependency.setArtifactId(artifactId);
505 dependency.setVersion(version);
506 dependency.setType("jar");
507 dependency.setScope("compile");
508
509 return factory.createDependencyArtifact(dependency);
510 }
511
512 private MojoExecution newMojoExecution() {
513 PluginDescriptor pd = new PluginDescriptor();
514 pd.setArtifactId("my-plugin");
515 pd.setGroupId("org.myco.plugins");
516 pd.setVersion("1");
517
518 MojoDescriptor md = new MojoDescriptor();
519 md.setPluginDescriptor(pd);
520
521 pd.addComponentDescriptor(md);
522
523 return new MojoExecution(md);
524 }
525
526 private MavenSession newMavenSession() throws Exception {
527 return createMavenSession(null);
528 }
529
530 @Override
531 protected String getProjectsDirectory() {
532
533 return null;
534 }
535
536 public static class Mojo {
537 URI uri;
538 Path path;
539 String uriString;
540 String uriAsciiString;
541 String pathString;
542 }
543 }