1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.model.interpolation;
20
21 import java.io.File;
22 import java.nio.file.Path;
23 import java.nio.file.Paths;
24 import java.text.SimpleDateFormat;
25 import java.util.Arrays;
26 import java.util.Calendar;
27 import java.util.Collections;
28 import java.util.Date;
29 import java.util.HashMap;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Properties;
34 import java.util.TimeZone;
35
36 import org.apache.maven.api.model.Build;
37 import org.apache.maven.api.model.Dependency;
38 import org.apache.maven.api.model.Model;
39 import org.apache.maven.api.model.Organization;
40 import org.apache.maven.api.model.Repository;
41 import org.apache.maven.api.model.Resource;
42 import org.apache.maven.api.model.Scm;
43 import org.apache.maven.model.building.DefaultModelBuildingRequest;
44 import org.apache.maven.model.building.ModelBuildingRequest;
45 import org.apache.maven.model.building.SimpleProblemCollector;
46 import org.apache.maven.model.root.RootLocator;
47 import org.junit.jupiter.api.BeforeEach;
48 import org.junit.jupiter.api.Test;
49
50 import static org.junit.jupiter.api.Assertions.assertEquals;
51 import static org.junit.jupiter.api.Assertions.assertNotNull;
52 import static org.junit.jupiter.api.Assertions.assertThrows;
53 import static org.junit.jupiter.api.Assertions.assertTrue;
54
55
56
57 public abstract class AbstractModelInterpolatorTest {
58 private Properties context;
59
60 @BeforeEach
61 public void setUp() {
62 context = new Properties();
63 context.put("basedir", "myBasedir");
64 context.put("project.baseUri", "myBaseUri");
65 }
66
67 protected void assertProblemFree(SimpleProblemCollector collector) {
68 assertEquals(0, collector.getErrors().size(), "Expected no errors");
69 assertEquals(0, collector.getWarnings().size(), "Expected no warnings");
70 assertEquals(0, collector.getFatals().size(), "Expected no fatals");
71 }
72
73 protected void assertCollectorState(
74 int numFatals, int numErrors, int numWarnings, SimpleProblemCollector collector) {
75 assertEquals(numErrors, collector.getErrors().size(), "Errors");
76 assertEquals(numWarnings, collector.getWarnings().size(), "Warnings");
77 assertEquals(numFatals, collector.getFatals().size(), "Fatals");
78 }
79
80 private ModelBuildingRequest createModelBuildingRequest(Properties p) {
81 ModelBuildingRequest config = new DefaultModelBuildingRequest();
82 if (p != null) {
83 config.setSystemProperties(p);
84 }
85 return config;
86 }
87
88 @Test
89 public void testDefaultBuildTimestampFormatShouldFormatTimeIn24HourFormat() {
90 Calendar cal = Calendar.getInstance();
91 cal.setTimeZone(MavenBuildTimestamp.DEFAULT_BUILD_TIME_ZONE);
92 cal.set(Calendar.HOUR, 12);
93 cal.set(Calendar.AM_PM, Calendar.AM);
94
95
96 cal.set(Calendar.HOUR_OF_DAY, 0);
97 cal.set(Calendar.MINUTE, 16);
98 cal.set(Calendar.SECOND, 0);
99 cal.set(Calendar.YEAR, 1976);
100 cal.set(Calendar.MONTH, Calendar.NOVEMBER);
101 cal.set(Calendar.DATE, 11);
102
103 Date firstTestDate = cal.getTime();
104
105 cal.set(Calendar.HOUR, 11);
106 cal.set(Calendar.AM_PM, Calendar.PM);
107
108
109 cal.set(Calendar.HOUR_OF_DAY, 23);
110
111 Date secondTestDate = cal.getTime();
112
113 SimpleDateFormat format = new SimpleDateFormat(MavenBuildTimestamp.DEFAULT_BUILD_TIMESTAMP_FORMAT);
114 format.setTimeZone(MavenBuildTimestamp.DEFAULT_BUILD_TIME_ZONE);
115 assertEquals("1976-11-11T00:16:00Z", format.format(firstTestDate));
116 assertEquals("1976-11-11T23:16:00Z", format.format(secondTestDate));
117 }
118
119 @Test
120 public void testDefaultBuildTimestampFormatWithLocalTimeZoneMidnightRollover() {
121 Calendar cal = Calendar.getInstance();
122 cal.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
123
124 cal.set(Calendar.HOUR_OF_DAY, 1);
125 cal.set(Calendar.MINUTE, 16);
126 cal.set(Calendar.SECOND, 0);
127 cal.set(Calendar.YEAR, 2014);
128 cal.set(Calendar.MONTH, Calendar.JUNE);
129 cal.set(Calendar.DATE, 16);
130
131 Date firstTestDate = cal.getTime();
132
133 cal.set(Calendar.MONTH, Calendar.NOVEMBER);
134
135 Date secondTestDate = cal.getTime();
136
137 SimpleDateFormat format = new SimpleDateFormat(MavenBuildTimestamp.DEFAULT_BUILD_TIMESTAMP_FORMAT);
138 format.setTimeZone(MavenBuildTimestamp.DEFAULT_BUILD_TIME_ZONE);
139 assertEquals("2014-06-15T23:16:00Z", format.format(firstTestDate));
140 assertEquals("2014-11-16T00:16:00Z", format.format(secondTestDate));
141 }
142
143 @Test
144 public void testShouldNotThrowExceptionOnReferenceToNonExistentValue() throws Exception {
145 Scm scm = Scm.newBuilder().connection("${test}/somepath").build();
146 Model model = Model.newBuilder().scm(scm).build();
147
148 ModelInterpolator interpolator = createInterpolator();
149
150 final SimpleProblemCollector collector = new SimpleProblemCollector();
151 Model out = interpolator.interpolateModel(model, new File("."), createModelBuildingRequest(context), collector);
152
153 assertProblemFree(collector);
154 assertEquals("${test}/somepath", out.getScm().getConnection());
155 }
156
157 @Test
158 public void testShouldThrowExceptionOnRecursiveScmConnectionReference() throws Exception {
159 Scm scm = Scm.newBuilder()
160 .connection("${project.scm.connection}/somepath")
161 .build();
162 Model model = Model.newBuilder().scm(scm).build();
163
164 ModelInterpolator interpolator = createInterpolator();
165
166 final SimpleProblemCollector collector = new SimpleProblemCollector();
167 interpolator.interpolateModel(model, (Path) null, createModelBuildingRequest(context), collector);
168 assertCollectorState(0, 1, 0, collector);
169 }
170
171 @Test
172 public void testShouldNotThrowExceptionOnReferenceToValueContainingNakedExpression() throws Exception {
173 Scm scm = Scm.newBuilder().connection("${test}/somepath").build();
174 Map<String, String> props = new HashMap<>();
175 props.put("test", "test");
176 Model model = Model.newBuilder().scm(scm).properties(props).build();
177
178 ModelInterpolator interpolator = createInterpolator();
179
180 final SimpleProblemCollector collector = new SimpleProblemCollector();
181 Model out = interpolator.interpolateModel(model, new File("."), createModelBuildingRequest(context), collector);
182
183 assertProblemFree(collector);
184
185 assertEquals("test/somepath", out.getScm().getConnection());
186 }
187
188 @Test
189 public void shouldInterpolateOrganizationNameCorrectly() throws Exception {
190 String orgName = "MyCo";
191
192 Model model = Model.newBuilder()
193 .name("${project.organization.name} Tools")
194 .organization(Organization.newBuilder().name(orgName).build())
195 .build();
196
197 ModelInterpolator interpolator = createInterpolator();
198
199 Model out = interpolator.interpolateModel(
200 model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector());
201
202 assertEquals(orgName + " Tools", out.getName());
203 }
204
205 @Test
206 public void shouldInterpolateDependencyVersionToSetSameAsProjectVersion() throws Exception {
207 Model model = Model.newBuilder()
208 .version("3.8.1")
209 .dependencies(Collections.singletonList(
210 Dependency.newBuilder().version("${project.version}").build()))
211 .build();
212
213 ModelInterpolator interpolator = createInterpolator();
214
215 final SimpleProblemCollector collector = new SimpleProblemCollector();
216 Model out = interpolator.interpolateModel(model, new File("."), createModelBuildingRequest(context), collector);
217 assertCollectorState(0, 0, 0, collector);
218
219 assertEquals("3.8.1", (out.getDependencies().get(0)).getVersion());
220 }
221
222 @Test
223 public void testShouldNotInterpolateDependencyVersionWithInvalidReference() throws Exception {
224 Model model = Model.newBuilder()
225 .version("3.8.1")
226 .dependencies(Collections.singletonList(
227 Dependency.newBuilder().version("${something}").build()))
228 .build();
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 ModelInterpolator interpolator = createInterpolator();
246
247 final SimpleProblemCollector collector = new SimpleProblemCollector();
248 Model out = interpolator.interpolateModel(model, new File("."), createModelBuildingRequest(context), collector);
249 assertProblemFree(collector);
250
251 assertEquals("${something}", (out.getDependencies().get(0)).getVersion());
252 }
253
254 @Test
255 public void testTwoReferences() throws Exception {
256 Model model = Model.newBuilder()
257 .version("3.8.1")
258 .artifactId("foo")
259 .dependencies(Collections.singletonList(Dependency.newBuilder()
260 .version("${project.artifactId}-${project.version}")
261 .build()))
262 .build();
263
264 ModelInterpolator interpolator = createInterpolator();
265
266 final SimpleProblemCollector collector = new SimpleProblemCollector();
267 Model out = interpolator.interpolateModel(model, new File("."), createModelBuildingRequest(context), collector);
268 assertCollectorState(0, 0, 0, collector);
269
270 assertEquals("foo-3.8.1", (out.getDependencies().get(0)).getVersion());
271 }
272
273 @Test
274 public void testBasedir() throws Exception {
275 Model model = Model.newBuilder()
276 .version("3.8.1")
277 .artifactId("foo")
278 .repositories(Collections.singletonList(Repository.newBuilder()
279 .url("file://localhost/${basedir}/temp-repo")
280 .build()))
281 .build();
282
283 ModelInterpolator interpolator = createInterpolator();
284
285 final SimpleProblemCollector collector = new SimpleProblemCollector();
286 Model out = interpolator.interpolateModel(model, (Path) null, createModelBuildingRequest(context), collector);
287 assertProblemFree(collector);
288
289 assertEquals(
290 "file://localhost/myBasedir/temp-repo", (out.getRepositories().get(0)).getUrl());
291 }
292
293 @Test
294 public void testBaseUri() throws Exception {
295 Model model = Model.newBuilder()
296 .version("3.8.1")
297 .artifactId("foo")
298 .repositories(Collections.singletonList(Repository.newBuilder()
299 .url("${project.baseUri}/temp-repo")
300 .build()))
301 .build();
302
303 ModelInterpolator interpolator = createInterpolator();
304
305 final SimpleProblemCollector collector = new SimpleProblemCollector();
306 Model out = interpolator.interpolateModel(model, (Path) null, createModelBuildingRequest(context), collector);
307 assertProblemFree(collector);
308
309 assertEquals("myBaseUri/temp-repo", (out.getRepositories().get(0)).getUrl());
310 }
311
312 @Test
313 void testRootDirectory() throws Exception {
314 Path rootDirectory = Paths.get("myRootDirectory");
315
316 Model model = Model.newBuilder()
317 .version("3.8.1")
318 .artifactId("foo")
319 .repositories(Collections.singletonList(Repository.newBuilder()
320 .url("file:${project.rootDirectory}/temp-repo")
321 .build()))
322 .build();
323
324 ModelInterpolator interpolator = createInterpolator();
325
326 final SimpleProblemCollector collector = new SimpleProblemCollector();
327 Model out = interpolator.interpolateModel(
328 model, rootDirectory.toFile(), createModelBuildingRequest(context), collector);
329 assertProblemFree(collector);
330
331 assertEquals("file:myRootDirectory/temp-repo", (out.getRepositories().get(0)).getUrl());
332 }
333
334 @Test
335 void testRootDirectoryWithUri() throws Exception {
336 Path rootDirectory = Paths.get("myRootDirectory");
337
338 Model model = Model.newBuilder()
339 .version("3.8.1")
340 .artifactId("foo")
341 .repositories(Collections.singletonList(Repository.newBuilder()
342 .url("${project.rootDirectory.uri}/temp-repo")
343 .build()))
344 .build();
345
346 ModelInterpolator interpolator = createInterpolator();
347
348 final SimpleProblemCollector collector = new SimpleProblemCollector();
349 Model out = interpolator.interpolateModel(
350 model, rootDirectory.toFile(), createModelBuildingRequest(context), collector);
351 assertProblemFree(collector);
352
353 assertEquals(
354 rootDirectory.resolve("temp-repo").toUri().toString(),
355 (out.getRepositories().get(0)).getUrl());
356 }
357
358 @Test
359 void testRootDirectoryWithNull() throws Exception {
360 Model model = Model.newBuilder()
361 .version("3.8.1")
362 .artifactId("foo")
363 .repositories(Collections.singletonList(Repository.newBuilder()
364 .url("file:///${project.rootDirectory}/temp-repo")
365 .build()))
366 .build();
367
368 ModelInterpolator interpolator = createInterpolator();
369
370 final SimpleProblemCollector collector = new SimpleProblemCollector();
371 IllegalStateException e = assertThrows(
372 IllegalStateException.class,
373 () -> interpolator.interpolateModel(
374 model, (Path) null, createModelBuildingRequest(context), collector));
375
376 assertEquals(RootLocator.UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE, e.getMessage());
377 }
378
379 @Test
380 public void testEnvars() throws Exception {
381 context.put("env.HOME", "/path/to/home");
382
383 Map<String, String> modelProperties = new HashMap<>();
384 modelProperties.put("outputDirectory", "${env.HOME}");
385
386 Model model = Model.newBuilder().properties(modelProperties).build();
387
388 ModelInterpolator interpolator = createInterpolator();
389
390 final SimpleProblemCollector collector = new SimpleProblemCollector();
391 Model out = interpolator.interpolateModel(model, new File("."), createModelBuildingRequest(context), collector);
392 assertProblemFree(collector);
393
394 assertEquals("/path/to/home", out.getProperties().get("outputDirectory"));
395 }
396
397 @Test
398 public void envarExpressionThatEvaluatesToNullReturnsTheLiteralString() throws Exception {
399
400 Map<String, String> modelProperties = new HashMap<>();
401 modelProperties.put("outputDirectory", "${env.DOES_NOT_EXIST}");
402
403 Model model = Model.newBuilder().properties(modelProperties).build();
404
405 ModelInterpolator interpolator = createInterpolator();
406
407 final SimpleProblemCollector collector = new SimpleProblemCollector();
408 Model out = interpolator.interpolateModel(model, new File("."), createModelBuildingRequest(context), collector);
409 assertProblemFree(collector);
410
411 assertEquals(out.getProperties().get("outputDirectory"), "${env.DOES_NOT_EXIST}");
412 }
413
414 @Test
415 public void expressionThatEvaluatesToNullReturnsTheLiteralString() throws Exception {
416 Map<String, String> modelProperties = new HashMap<>();
417 modelProperties.put("outputDirectory", "${DOES_NOT_EXIST}");
418
419 Model model = Model.newBuilder().properties(modelProperties).build();
420
421 ModelInterpolator interpolator = createInterpolator();
422
423 final SimpleProblemCollector collector = new SimpleProblemCollector();
424 Model out = interpolator.interpolateModel(model, new File("."), createModelBuildingRequest(context), collector);
425 assertProblemFree(collector);
426
427 assertEquals(out.getProperties().get("outputDirectory"), "${DOES_NOT_EXIST}");
428 }
429
430 @Test
431 public void shouldInterpolateSourceDirectoryReferencedFromResourceDirectoryCorrectly() throws Exception {
432 Model model = Model.newBuilder()
433 .build(Build.newBuilder()
434 .sourceDirectory("correct")
435 .resources(Arrays.asList(Resource.newBuilder()
436 .directory("${project.build.sourceDirectory}")
437 .build()))
438 .build())
439 .build();
440
441 ModelInterpolator interpolator = createInterpolator();
442
443 final SimpleProblemCollector collector = new SimpleProblemCollector();
444 Model out = interpolator.interpolateModel(model, (Path) null, createModelBuildingRequest(context), collector);
445 assertCollectorState(0, 0, 0, collector);
446
447 List<Resource> outResources = out.getBuild().getResources();
448 Iterator<Resource> resIt = outResources.iterator();
449
450 assertEquals(model.getBuild().getSourceDirectory(), resIt.next().getDirectory());
451 }
452
453 @Test
454 public void shouldInterpolateUnprefixedBasedirExpression() throws Exception {
455 File basedir = new File("/test/path");
456 Model model = Model.newBuilder()
457 .dependencies(Collections.singletonList(Dependency.newBuilder()
458 .systemPath("${basedir}/artifact.jar")
459 .build()))
460 .build();
461
462 ModelInterpolator interpolator = createInterpolator();
463
464 final SimpleProblemCollector collector = new SimpleProblemCollector();
465 Model result = interpolator.interpolateModel(model, basedir, createModelBuildingRequest(context), collector);
466 assertProblemFree(collector);
467
468 List<Dependency> rDeps = result.getDependencies();
469 assertNotNull(rDeps);
470 assertEquals(1, rDeps.size());
471 assertEquals(
472 new File(basedir, "artifact.jar").getAbsolutePath(),
473 new File(rDeps.get(0).getSystemPath()).getAbsolutePath());
474 }
475
476 @Test
477 public void testRecursiveExpressionCycleNPE() throws Exception {
478 Map<String, String> props = new HashMap<>();
479 props.put("aa", "${bb}");
480 props.put("bb", "${aa}");
481 DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
482
483 Model model = Model.newBuilder().properties(props).build();
484
485 SimpleProblemCollector collector = new SimpleProblemCollector();
486 ModelInterpolator interpolator = createInterpolator();
487 interpolator.interpolateModel(model, (Path) null, request, collector);
488
489 assertCollectorState(0, 2, 0, collector);
490 assertTrue(collector.getErrors().get(0).contains("Detected the following recursive expression cycle"));
491 }
492
493 @Test
494 public void testRecursiveExpressionCycleBaseDir() throws Exception {
495 Map<String, String> props = new HashMap<>();
496 props.put("basedir", "${basedir}");
497 DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
498
499 Model model = Model.newBuilder().properties(props).build();
500
501 SimpleProblemCollector collector = new SimpleProblemCollector();
502 ModelInterpolator interpolator = createInterpolator();
503 interpolator.interpolateModel(model, (Path) null, request, collector);
504
505 assertCollectorState(0, 1, 0, collector);
506 assertEquals(
507 "Resolving expression: '${basedir}': Detected the following recursive expression cycle in 'basedir': [basedir]",
508 collector.getErrors().get(0));
509 }
510
511 @Test
512 public void shouldIgnorePropertiesWithPomPrefix() throws Exception {
513 final String orgName = "MyCo";
514 final String uninterpolatedName = "${pom.organization.name} Tools";
515 final String interpolatedName = uninterpolatedName;
516
517 Model model = Model.newBuilder()
518 .name(uninterpolatedName)
519 .organization(Organization.newBuilder().name(orgName).build())
520 .build();
521
522 ModelInterpolator interpolator = createInterpolator();
523 SimpleProblemCollector collector = new SimpleProblemCollector();
524 Model out = interpolator.interpolateModel(
525 model,
526 (Path) null,
527 createModelBuildingRequest(context).setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_4_0),
528 collector);
529
530 assertCollectorState(0, 0, 0, collector);
531 assertEquals(interpolatedName, out.getName());
532 }
533
534 @Test
535 public void shouldWarnPropertiesWithPomPrefix() throws Exception {
536 final String orgName = "MyCo";
537 final String uninterpolatedName = "${pom.organization.name} Tools";
538 final String interpolatedName = "MyCo Tools";
539
540 Model model = Model.newBuilder()
541 .name(uninterpolatedName)
542 .organization(Organization.newBuilder().name(orgName).build())
543 .build();
544
545 ModelInterpolator interpolator = createInterpolator();
546 SimpleProblemCollector collector = new SimpleProblemCollector();
547 Model out = interpolator.interpolateModel(
548 model,
549 (Path) null,
550 createModelBuildingRequest(context).setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_1),
551 collector);
552
553 assertCollectorState(0, 0, 1, collector);
554 assertEquals(interpolatedName, out.getName());
555 }
556
557 protected abstract ModelInterpolator createInterpolator() throws Exception;
558 }