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, 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, 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, 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(model, null, createModelBuildingRequest(context), collector));
374
375 assertEquals(RootLocator.UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE, e.getMessage());
376 }
377
378 @Test
379 public void testEnvars() throws Exception {
380 context.put("env.HOME", "/path/to/home");
381
382 Map<String, String> modelProperties = new HashMap<>();
383 modelProperties.put("outputDirectory", "${env.HOME}");
384
385 Model model = Model.newBuilder().properties(modelProperties).build();
386
387 ModelInterpolator interpolator = createInterpolator();
388
389 final SimpleProblemCollector collector = new SimpleProblemCollector();
390 Model out = interpolator.interpolateModel(model, new File("."), createModelBuildingRequest(context), collector);
391 assertProblemFree(collector);
392
393 assertEquals("/path/to/home", out.getProperties().get("outputDirectory"));
394 }
395
396 @Test
397 public void envarExpressionThatEvaluatesToNullReturnsTheLiteralString() throws Exception {
398
399 Map<String, String> modelProperties = new HashMap<>();
400 modelProperties.put("outputDirectory", "${env.DOES_NOT_EXIST}");
401
402 Model model = Model.newBuilder().properties(modelProperties).build();
403
404 ModelInterpolator interpolator = createInterpolator();
405
406 final SimpleProblemCollector collector = new SimpleProblemCollector();
407 Model out = interpolator.interpolateModel(model, new File("."), createModelBuildingRequest(context), collector);
408 assertProblemFree(collector);
409
410 assertEquals(out.getProperties().get("outputDirectory"), "${env.DOES_NOT_EXIST}");
411 }
412
413 @Test
414 public void expressionThatEvaluatesToNullReturnsTheLiteralString() throws Exception {
415 Map<String, String> modelProperties = new HashMap<>();
416 modelProperties.put("outputDirectory", "${DOES_NOT_EXIST}");
417
418 Model model = Model.newBuilder().properties(modelProperties).build();
419
420 ModelInterpolator interpolator = createInterpolator();
421
422 final SimpleProblemCollector collector = new SimpleProblemCollector();
423 Model out = interpolator.interpolateModel(model, new File("."), createModelBuildingRequest(context), collector);
424 assertProblemFree(collector);
425
426 assertEquals(out.getProperties().get("outputDirectory"), "${DOES_NOT_EXIST}");
427 }
428
429 @Test
430 public void shouldInterpolateSourceDirectoryReferencedFromResourceDirectoryCorrectly() throws Exception {
431 Model model = Model.newBuilder()
432 .build(Build.newBuilder()
433 .sourceDirectory("correct")
434 .resources(Arrays.asList(Resource.newBuilder()
435 .directory("${project.build.sourceDirectory}")
436 .build()))
437 .build())
438 .build();
439
440 ModelInterpolator interpolator = createInterpolator();
441
442 final SimpleProblemCollector collector = new SimpleProblemCollector();
443 Model out = interpolator.interpolateModel(model, null, createModelBuildingRequest(context), collector);
444 assertCollectorState(0, 0, 0, collector);
445
446 List<Resource> outResources = out.getBuild().getResources();
447 Iterator<Resource> resIt = outResources.iterator();
448
449 assertEquals(model.getBuild().getSourceDirectory(), resIt.next().getDirectory());
450 }
451
452 @Test
453 public void shouldInterpolateUnprefixedBasedirExpression() throws Exception {
454 File basedir = new File("/test/path");
455 Model model = Model.newBuilder()
456 .dependencies(Collections.singletonList(Dependency.newBuilder()
457 .systemPath("${basedir}/artifact.jar")
458 .build()))
459 .build();
460
461 ModelInterpolator interpolator = createInterpolator();
462
463 final SimpleProblemCollector collector = new SimpleProblemCollector();
464 Model result = interpolator.interpolateModel(model, basedir, createModelBuildingRequest(context), collector);
465 assertProblemFree(collector);
466
467 List<Dependency> rDeps = result.getDependencies();
468 assertNotNull(rDeps);
469 assertEquals(1, rDeps.size());
470 assertEquals(
471 new File(basedir, "artifact.jar").getAbsolutePath(),
472 new File(rDeps.get(0).getSystemPath()).getAbsolutePath());
473 }
474
475 @Test
476 public void testRecursiveExpressionCycleNPE() throws Exception {
477 Map<String, String> props = new HashMap<>();
478 props.put("aa", "${bb}");
479 props.put("bb", "${aa}");
480 DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
481
482 Model model = Model.newBuilder().properties(props).build();
483
484 SimpleProblemCollector collector = new SimpleProblemCollector();
485 ModelInterpolator interpolator = createInterpolator();
486 interpolator.interpolateModel(model, null, request, collector);
487
488 assertCollectorState(0, 2, 0, collector);
489 assertTrue(collector.getErrors().get(0).contains("Detected the following recursive expression cycle"));
490 }
491
492 @Test
493 public void testRecursiveExpressionCycleBaseDir() throws Exception {
494 Map<String, String> props = new HashMap<>();
495 props.put("basedir", "${basedir}");
496 DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
497
498 Model model = Model.newBuilder().properties(props).build();
499
500 SimpleProblemCollector collector = new SimpleProblemCollector();
501 ModelInterpolator interpolator = createInterpolator();
502 interpolator.interpolateModel(model, null, request, collector);
503
504 assertCollectorState(0, 1, 0, collector);
505 assertEquals(
506 "Resolving expression: '${basedir}': Detected the following recursive expression cycle in 'basedir': [basedir]",
507 collector.getErrors().get(0));
508 }
509
510 @Test
511 public void shouldIgnorePropertiesWithPomPrefix() throws Exception {
512 final String orgName = "MyCo";
513 final String uninterpolatedName = "${pom.organization.name} Tools";
514 final String interpolatedName = uninterpolatedName;
515
516 Model model = Model.newBuilder()
517 .name(uninterpolatedName)
518 .organization(Organization.newBuilder().name(orgName).build())
519 .build();
520
521 ModelInterpolator interpolator = createInterpolator();
522 SimpleProblemCollector collector = new SimpleProblemCollector();
523 Model out = interpolator.interpolateModel(
524 model,
525 null,
526 createModelBuildingRequest(context).setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_4_0),
527 collector);
528
529 assertCollectorState(0, 0, 0, collector);
530 assertEquals(interpolatedName, out.getName());
531 }
532
533 @Test
534 public void shouldWarnPropertiesWithPomPrefix() throws Exception {
535 final String orgName = "MyCo";
536 final String uninterpolatedName = "${pom.organization.name} Tools";
537 final String interpolatedName = "MyCo Tools";
538
539 Model model = Model.newBuilder()
540 .name(uninterpolatedName)
541 .organization(Organization.newBuilder().name(orgName).build())
542 .build();
543
544 ModelInterpolator interpolator = createInterpolator();
545 SimpleProblemCollector collector = new SimpleProblemCollector();
546 Model out = interpolator.interpolateModel(
547 model,
548 null,
549 createModelBuildingRequest(context).setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_1),
550 collector);
551
552 assertCollectorState(0, 0, 1, collector);
553 assertEquals(interpolatedName, out.getName());
554 }
555
556 protected abstract ModelInterpolator createInterpolator() throws Exception;
557 }