1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.archiver;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.net.URI;
25 import java.net.URL;
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28 import java.nio.file.Paths;
29 import java.nio.file.attribute.FileTime;
30 import java.time.Instant;
31 import java.time.format.DateTimeParseException;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collections;
35 import java.util.Comparator;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Properties;
40 import java.util.Set;
41 import java.util.TreeSet;
42 import java.util.jar.Attributes;
43 import java.util.jar.JarFile;
44 import java.util.jar.Manifest;
45 import java.util.stream.Stream;
46 import java.util.zip.ZipEntry;
47 import java.util.zip.ZipFile;
48
49 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
50 import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
51 import org.apache.maven.artifact.Artifact;
52 import org.apache.maven.artifact.handler.ArtifactHandler;
53 import org.apache.maven.artifact.handler.DefaultArtifactHandler;
54 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
55 import org.apache.maven.execution.MavenSession;
56 import org.apache.maven.model.Build;
57 import org.apache.maven.model.Model;
58 import org.apache.maven.model.Organization;
59 import org.apache.maven.project.MavenProject;
60 import org.codehaus.plexus.archiver.jar.JarArchiver;
61 import org.codehaus.plexus.archiver.jar.ManifestException;
62 import org.junit.jupiter.api.Test;
63 import org.junit.jupiter.api.condition.EnabledForJreRange;
64 import org.junit.jupiter.api.condition.JRE;
65 import org.junit.jupiter.params.ParameterizedTest;
66 import org.junit.jupiter.params.provider.CsvSource;
67 import org.junit.jupiter.params.provider.EmptySource;
68 import org.junit.jupiter.params.provider.NullAndEmptySource;
69 import org.junit.jupiter.params.provider.ValueSource;
70
71 import static org.apache.maven.archiver.MavenArchiver.parseBuildOutputTimestamp;
72 import static org.assertj.core.api.Assertions.assertThat;
73 import static org.assertj.core.api.Assertions.assertThatCode;
74 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
75 import static org.codehaus.plexus.archiver.util.Streams.bufferedOutputStream;
76 import static org.codehaus.plexus.archiver.util.Streams.fileOutputStream;
77 import static org.junit.jupiter.api.Assertions.assertTrue;
78 import static org.mockito.Mockito.mock;
79 import static org.mockito.Mockito.when;
80
81 class MavenArchiverTest {
82 static class ArtifactComparator implements Comparator<Artifact> {
83 public int compare(Artifact o1, Artifact o2) {
84 return o1.getArtifactId().compareTo(o2.getArtifactId());
85 }
86 }
87
88 @ParameterizedTest
89 @EmptySource
90 @ValueSource(
91 strings = {
92 ".",
93 "dash-is-invalid",
94 "plus+is+invalid",
95 "colon:is:invalid",
96 "new.class",
97 "123.at.start.is.invalid",
98 "digit.at.123start.is.invalid"
99 })
100 void testInvalidModuleNames(String value) {
101 assertThat(MavenArchiver.isValidModuleName(value)).isFalse();
102 }
103
104 @ParameterizedTest
105 @ValueSource(strings = {"a", "a.b", "a_b", "trailing0.digits123.are456.ok789", "UTF8.chars.are.okay.äëïöüẍ", "ℤ€ℕ"})
106 void testValidModuleNames(String value) {
107 assertThat(MavenArchiver.isValidModuleName(value)).isTrue();
108 }
109
110 @Test
111 void testGetManifestExtensionList() throws Exception {
112 MavenArchiver archiver = new MavenArchiver();
113
114 MavenSession session = getDummySession();
115
116 Model model = new Model();
117 model.setArtifactId("dummy");
118
119 MavenProject project = new MavenProject(model);
120
121 Set<Artifact> artifacts = new TreeSet<>(new ArtifactComparator());
122 project.setArtifacts(artifacts);
123
124
125 ManifestConfiguration config = new ManifestConfiguration() {
126 public boolean isAddExtensions() {
127 return true;
128 }
129 };
130
131 Manifest manifest = archiver.getManifest(session, project, config);
132
133 assertThat(manifest.getMainAttributes()).isNotNull();
134
135 assertThat(manifest.getMainAttributes().getValue("Extension-List")).isNull();
136
137 Artifact artifact1 = mock(Artifact.class);
138 when(artifact1.getGroupId()).thenReturn("org.apache.dummy");
139 when(artifact1.getArtifactId()).thenReturn("dummy1");
140 when(artifact1.getVersion()).thenReturn("1.0");
141 when(artifact1.getType()).thenReturn("dll");
142 when(artifact1.getScope()).thenReturn("compile");
143
144 artifacts.add(artifact1);
145
146 manifest = archiver.getManifest(session, project, config);
147
148 assertThat(manifest.getMainAttributes().getValue("Extension-List")).isNull();
149
150 Artifact artifact2 = mock(Artifact.class);
151 when(artifact2.getGroupId()).thenReturn("org.apache.dummy");
152 when(artifact2.getArtifactId()).thenReturn("dummy2");
153 when(artifact2.getVersion()).thenReturn("1.0");
154 when(artifact2.getType()).thenReturn("jar");
155 when(artifact2.getScope()).thenReturn("compile");
156
157 artifacts.add(artifact2);
158
159 manifest = archiver.getManifest(session, project, config);
160
161 assertThat(manifest.getMainAttributes().getValue("Extension-List")).isEqualTo("dummy2");
162
163 Artifact artifact3 = mock(Artifact.class);
164 when(artifact3.getGroupId()).thenReturn("org.apache.dummy");
165 when(artifact3.getArtifactId()).thenReturn("dummy3");
166 when(artifact3.getVersion()).thenReturn("1.0");
167 when(artifact3.getType()).thenReturn("jar");
168 when(artifact3.getScope()).thenReturn("test");
169
170 artifacts.add(artifact3);
171
172 manifest = archiver.getManifest(session, project, config);
173
174 assertThat(manifest.getMainAttributes().getValue("Extension-List")).isEqualTo("dummy2");
175
176 Artifact artifact4 = mock(Artifact.class);
177 when(artifact4.getGroupId()).thenReturn("org.apache.dummy");
178 when(artifact4.getArtifactId()).thenReturn("dummy4");
179 when(artifact4.getVersion()).thenReturn("1.0");
180 when(artifact4.getType()).thenReturn("jar");
181 when(artifact4.getScope()).thenReturn("compile");
182
183 artifacts.add(artifact4);
184
185 manifest = archiver.getManifest(session, project, config);
186
187 assertThat(manifest.getMainAttributes().getValue("Extension-List")).isEqualTo("dummy2 dummy4");
188 }
189
190 @Test
191 void testMultiClassPath() throws Exception {
192 final File tempFile = File.createTempFile("maven-archiver-test-", ".jar");
193
194 try {
195 MavenArchiver archiver = new MavenArchiver();
196
197 MavenSession session = getDummySession();
198
199 Model model = new Model();
200 model.setArtifactId("dummy");
201
202 MavenProject project = new MavenProject(model) {
203 public List<String> getRuntimeClasspathElements() {
204 return Collections.singletonList(tempFile.getAbsolutePath());
205 }
206 };
207
208
209 ManifestConfiguration manifestConfig = new ManifestConfiguration() {
210 public boolean isAddClasspath() {
211 return true;
212 }
213 };
214
215 MavenArchiveConfiguration archiveConfiguration = new MavenArchiveConfiguration();
216 archiveConfiguration.setManifest(manifestConfig);
217 archiveConfiguration.addManifestEntry("Class-Path", "help/");
218
219 Manifest manifest = archiver.getManifest(session, project, archiveConfiguration);
220 String classPath = manifest.getMainAttributes().getValue("Class-Path");
221 assertThat(classPath)
222 .as("User specified Class-Path entry was not prepended to manifest")
223 .startsWith("help/")
224 .as("Class-Path generated by addClasspath was not appended to manifest")
225 .endsWith(tempFile.getName());
226 } finally {
227
228 tempFile.delete();
229 }
230 }
231
232 @Test
233 void testRecreation() throws Exception {
234 File jarFile = new File("target/test/dummy.jar");
235 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
236
237 MavenArchiver archiver = getMavenArchiver(jarArchiver);
238
239 MavenSession session = getDummySession();
240 MavenProject project = getDummyProject();
241
242 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
243 config.setForced(false);
244
245 Path directory = Paths.get("target", "maven-archiver");
246 if (Files.exists(directory)) {
247 try (Stream<Path> paths = Files.walk(directory)) {
248 paths.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
249 }
250 }
251
252 archiver.createArchive(session, project, config);
253 assertThat(jarFile).exists();
254
255 long history = System.currentTimeMillis() - 60000L;
256 jarFile.setLastModified(history);
257 long time = jarFile.lastModified();
258
259 try (Stream<Path> paths = Files.walk(directory)) {
260 FileTime fileTime = FileTime.fromMillis(time);
261 paths.forEach(path -> assertThatCode(() -> Files.setLastModifiedTime(path, fileTime))
262 .doesNotThrowAnyException());
263 }
264
265 archiver.createArchive(session, project, config);
266
267 config.setForced(true);
268 archiver.createArchive(session, project, config);
269
270 assertThat(jarFile.lastModified()).isGreaterThanOrEqualTo(time);
271 }
272
273 @Test
274 void testNotGenerateImplementationVersionForMANIFESTMF() throws Exception {
275 File jarFile = new File("target/test/dummy.jar");
276 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
277
278 MavenArchiver archiver = getMavenArchiver(jarArchiver);
279
280 MavenSession session = getDummySession();
281 MavenProject project = getDummyProject();
282
283 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
284 config.setForced(true);
285 config.getManifest().setAddDefaultImplementationEntries(false);
286 archiver.createArchive(session, project, config);
287 assertThat(jarFile).exists();
288
289 try (JarFile jar = new JarFile(jarFile)) {
290 assertThat(jar.getManifest().getMainAttributes())
291 .doesNotContainKey(Attributes.Name.IMPLEMENTATION_VERSION);
292 }
293 }
294
295 @Test
296 void testGenerateImplementationVersionForMANIFESTMF() throws Exception {
297 File jarFile = new File("target/test/dummy.jar");
298 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
299
300 MavenArchiver archiver = getMavenArchiver(jarArchiver);
301
302 MavenSession session = getDummySession();
303 MavenProject project = getDummyProject();
304
305 String ls = System.getProperty("line.separator");
306 project.setDescription("foo " + ls + " bar ");
307 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
308 config.setForced(true);
309 config.getManifest().setAddDefaultImplementationEntries(true);
310 config.addManifestEntry("Description", project.getDescription());
311 archiver.createArchive(session, project, config);
312 assertThat(jarFile).exists();
313
314 try (JarFile jar = new JarFile(jarFile)) {
315 assertThat(jar.getManifest().getMainAttributes())
316 .containsKey(Attributes.Name.IMPLEMENTATION_VERSION)
317 .containsEntry(Attributes.Name.IMPLEMENTATION_VERSION, "0.1.1");
318 }
319 }
320
321 private MavenArchiver getMavenArchiver(JarArchiver jarArchiver) {
322 MavenArchiver archiver = new MavenArchiver();
323 archiver.setArchiver(jarArchiver);
324 archiver.setOutputFile(jarArchiver.getDestFile());
325 return archiver;
326 }
327
328 @Test
329 void testDashesInClassPathMSHARED134() throws Exception {
330 File jarFile = new File("target/test/dummyWithDashes.jar");
331 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
332
333 MavenArchiver archiver = getMavenArchiver(jarArchiver);
334
335 MavenSession session = getDummySession();
336 MavenProject project = getDummyProject();
337
338 Set<Artifact> artifacts =
339 getArtifacts(getMockArtifact1(), getArtifactWithDot(), getMockArtifact2(), getMockArtifact3());
340
341 project.setArtifacts(artifacts);
342
343 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
344 config.setForced(false);
345
346 final ManifestConfiguration mftConfig = config.getManifest();
347 mftConfig.setMainClass("org.apache.maven.Foo");
348 mftConfig.setAddClasspath(true);
349 mftConfig.setAddExtensions(true);
350 mftConfig.setClasspathPrefix("./lib/");
351
352 archiver.createArchive(session, project, config);
353 assertThat(jarFile).exists();
354 }
355
356 @Test
357 void testDashesInClassPathMSHARED182() throws Exception {
358 File jarFile = new File("target/test/dummy.jar");
359 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
360 MavenArchiver archiver = getMavenArchiver(jarArchiver);
361
362 MavenSession session = getDummySession();
363 MavenProject project = getDummyProject();
364
365 Set<Artifact> artifacts =
366 getArtifacts(getMockArtifact1(), getArtifactWithDot(), getMockArtifact2(), getMockArtifact3());
367
368 project.setArtifacts(artifacts);
369
370 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
371 config.setForced(false);
372
373 final ManifestConfiguration mftConfig = config.getManifest();
374 mftConfig.setMainClass("org.apache.maven.Foo");
375 mftConfig.setAddClasspath(true);
376 mftConfig.setAddExtensions(true);
377 mftConfig.setClasspathPrefix("./lib/");
378 config.addManifestEntry("Key1", "value1");
379 config.addManifestEntry("key2", "value2");
380
381 archiver.createArchive(session, project, config);
382 assertThat(jarFile).exists();
383 final Attributes mainAttributes = getJarFileManifest(jarFile).getMainAttributes();
384 assertThat(mainAttributes.getValue("Key1")).isEqualTo("value1");
385 assertThat(mainAttributes.getValue("Key2")).isEqualTo("value2");
386 }
387
388 @Test
389 void testCarriageReturnInManifestEntry() throws Exception {
390 File jarFile = new File("target/test/dummy.jar");
391 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
392
393 MavenArchiver archiver = getMavenArchiver(jarArchiver);
394
395 MavenSession session = getDummySession();
396 MavenProject project = getDummyProject();
397
398 String ls = System.getProperty("line.separator");
399 project.setDescription("foo " + ls + " bar ");
400 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
401 config.setForced(true);
402 config.getManifest().setAddDefaultImplementationEntries(true);
403 config.addManifestEntry("Description", project.getDescription());
404
405
406 archiver.createArchive(session, project, config);
407 assertThat(jarFile).exists();
408
409 final Manifest manifest = getJarFileManifest(jarFile);
410 Attributes attributes = manifest.getMainAttributes();
411 assertThat(project.getDescription().indexOf(ls)).isGreaterThan(0);
412 Attributes.Name description = new Attributes.Name("Description");
413 String value = attributes.getValue(description);
414 assertThat(value).isNotNull();
415 assertThat(value.indexOf(ls)).isLessThanOrEqualTo(0);
416 }
417
418 @Test
419 void testDeprecatedCreateArchiveAPI() throws Exception {
420 File jarFile = new File("target/test/dummy.jar");
421 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
422
423 MavenArchiver archiver = getMavenArchiver(jarArchiver);
424
425 MavenProject project = getDummyProject();
426 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
427 config.setForced(true);
428 config.getManifest().setAddDefaultImplementationEntries(true);
429 config.getManifest().setAddDefaultSpecificationEntries(true);
430
431 MavenSession session = getDummySessionWithoutMavenVersion();
432 archiver.createArchive(session, project, config);
433 assertThat(jarFile).exists();
434 Attributes manifest = getJarFileManifest(jarFile).getMainAttributes();
435
436
437 assertThat(manifest)
438 .containsEntry(new Attributes.Name("Created-By"), "Maven Archiver")
439 .containsEntry(Attributes.Name.SPECIFICATION_TITLE, "archiver test")
440 .containsEntry(Attributes.Name.SPECIFICATION_VERSION, "0.1")
441 .containsEntry(Attributes.Name.SPECIFICATION_VENDOR, "Apache")
442 .containsEntry(Attributes.Name.IMPLEMENTATION_TITLE, "archiver test")
443 .containsEntry(Attributes.Name.IMPLEMENTATION_VERSION, "0.1.1")
444 .containsEntry(Attributes.Name.IMPLEMENTATION_VENDOR, "Apache")
445 .containsEntry(new Attributes.Name("Build-Jdk-Spec"), System.getProperty("java.specification.version"));
446 }
447
448 @Test
449 void testMinimalManifestEntries() throws Exception {
450 File jarFile = new File("target/test/dummy.jar");
451 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
452
453 MavenArchiver archiver = getMavenArchiver(jarArchiver);
454
455 MavenSession session = getDummySession();
456 MavenProject project = getDummyProject();
457 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
458 config.setForced(true);
459 config.getManifest().setAddDefaultEntries(false);
460
461 archiver.createArchive(session, project, config);
462 assertThat(jarFile).exists();
463
464 final Manifest jarFileManifest = getJarFileManifest(jarFile);
465 Attributes manifest = jarFileManifest.getMainAttributes();
466
467 assertThat(manifest).hasSize(1).containsOnlyKeys(new Attributes.Name("Manifest-Version"));
468 assertThat(manifest.getValue("Manifest-Version")).isEqualTo("1.0");
469 }
470
471 @Test
472 void testManifestEntries() throws Exception {
473 File jarFile = new File("target/test/dummy.jar");
474 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
475
476 MavenArchiver archiver = getMavenArchiver(jarArchiver);
477
478 MavenSession session = getDummySession();
479 MavenProject project = getDummyProject();
480 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
481 config.setForced(true);
482 config.getManifest().setAddDefaultImplementationEntries(true);
483 config.getManifest().setAddDefaultSpecificationEntries(true);
484 config.getManifest().setAddBuildEnvironmentEntries(true);
485
486 Map<String, String> manifestEntries = new HashMap<>();
487 manifestEntries.put("foo", "bar");
488 manifestEntries.put("first-name", "olivier");
489 manifestEntries.put("Automatic-Module-Name", "org.apache.maven.archiver");
490 manifestEntries.put("keyWithEmptyValue", null);
491 config.setManifestEntries(manifestEntries);
492
493 ManifestSection manifestSection = new ManifestSection();
494 manifestSection.setName("UserSection");
495 manifestSection.addManifestEntry("key", "value");
496 List<ManifestSection> manifestSections = new ArrayList<>();
497 manifestSections.add(manifestSection);
498 config.setManifestSections(manifestSections);
499 config.getManifest().setMainClass("org.apache.maven.Foo");
500 archiver.createArchive(session, project, config);
501 assertThat(jarFile).exists();
502
503 final Manifest jarFileManifest = getJarFileManifest(jarFile);
504 Attributes manifest = jarFileManifest.getMainAttributes();
505
506
507 assertThat(manifest)
508 .containsEntry(new Attributes.Name("Created-By"), "Maven Archiver")
509 .containsEntry(
510 new Attributes.Name("Build-Tool"),
511 session.getSystemProperties().get("maven.build.version"))
512 .containsEntry(
513 new Attributes.Name("Build-Jdk"),
514 String.format("%s (%s)", System.getProperty("java.version"), System.getProperty("java.vendor")))
515 .containsEntry(
516 new Attributes.Name("Build-Os"),
517 String.format(
518 "%s (%s; %s)",
519 System.getProperty("os.name"),
520 System.getProperty("os.version"),
521 System.getProperty("os.arch")))
522 .containsEntry(Attributes.Name.SPECIFICATION_TITLE, "archiver test")
523 .containsEntry(Attributes.Name.SPECIFICATION_VERSION, "0.1")
524 .containsEntry(Attributes.Name.SPECIFICATION_VENDOR, "Apache")
525 .containsEntry(Attributes.Name.IMPLEMENTATION_TITLE, "archiver test")
526 .containsEntry(Attributes.Name.IMPLEMENTATION_VERSION, "0.1.1")
527 .containsEntry(Attributes.Name.IMPLEMENTATION_VENDOR, "Apache")
528 .containsEntry(Attributes.Name.MAIN_CLASS, "org.apache.maven.Foo")
529 .containsEntry(new Attributes.Name("foo"), "bar")
530 .containsEntry(new Attributes.Name("first-name"), "olivier");
531
532 assertThat(manifest.getValue("Automatic-Module-Name")).isEqualTo("org.apache.maven.archiver");
533
534 assertThat(manifest)
535 .containsEntry(new Attributes.Name("Build-Jdk-Spec"), System.getProperty("java.specification.version"));
536
537 assertThat(manifest.getValue(new Attributes.Name("keyWithEmptyValue"))).isEmpty();
538 assertThat(manifest).containsKey(new Attributes.Name("keyWithEmptyValue"));
539
540 manifest = jarFileManifest.getAttributes("UserSection");
541
542 assertThat(manifest).containsEntry(new Attributes.Name("key"), "value");
543 }
544
545 @Test
546 void testManifestWithInvalidAutomaticModuleNameThrowsOnCreateArchive() throws Exception {
547 File jarFile = new File("target/test/dummy.jar");
548 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
549
550 MavenArchiver archiver = getMavenArchiver(jarArchiver);
551
552 MavenSession session = getDummySession();
553 MavenProject project = getDummyProject();
554 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
555
556 Map<String, String> manifestEntries = new HashMap<>();
557 manifestEntries.put("Automatic-Module-Name", "123.in-valid.new.name");
558 config.setManifestEntries(manifestEntries);
559
560 try {
561 archiver.createArchive(session, project, config);
562 } catch (ManifestException e) {
563 assertThat(e.getMessage()).isEqualTo("Invalid automatic module name: '123.in-valid.new.name'");
564 }
565 }
566
567
568
569
570
571 @Test
572 void testManifestWithEmptyAutomaticModuleName() throws Exception {
573 File jarFile = new File("target/test/dummy.jar");
574 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
575
576 MavenArchiver archiver = getMavenArchiver(jarArchiver);
577
578 MavenSession session = getDummySession();
579 MavenProject project = getDummyProject();
580 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
581
582 Map<String, String> manifestEntries = new HashMap<>();
583 manifestEntries.put("Automatic-Module-Name", "");
584 config.setManifestEntries(manifestEntries);
585
586 archiver.createArchive(session, project, config);
587 assertThat(jarFile).exists();
588
589 final Manifest jarFileManifest = getJarFileManifest(jarFile);
590 Attributes manifest = jarFileManifest.getMainAttributes();
591
592 assertThat(manifest).doesNotContainKey(new Attributes.Name("Automatic-Module-Name"));
593 }
594
595
596
597
598 @Test
599 void testManifestSections() throws Exception {
600 MavenArchiver archiver = new MavenArchiver();
601
602 MavenSession session = getDummySession();
603
604 MavenProject project = getDummyProject();
605 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
606
607 ManifestSection manifestSection = new ManifestSection();
608 manifestSection.setName("SectionOne");
609 manifestSection.addManifestEntry("key", "value");
610 List<ManifestSection> manifestSections = new ArrayList<>();
611 manifestSections.add(manifestSection);
612 config.setManifestSections(manifestSections);
613
614 Manifest manifest = archiver.getManifest(session, project, config);
615
616 Attributes section = manifest.getAttributes("SectionOne");
617 assertThat(section)
618 .as("The section is not present in the manifest as it should be.")
619 .isNotNull();
620
621 String attribute = section.getValue("key");
622 assertThat(attribute)
623 .as("The attribute we are looking for is not present in the section.")
624 .isNotNull()
625 .as("The value of the attribute is wrong.")
626 .isEqualTo("value");
627 }
628
629 @Test
630 void testDefaultClassPathValue() throws Exception {
631 MavenSession session = getDummySession();
632 MavenProject project = getDummyProject();
633 File jarFile = new File("target/test/dummy.jar");
634 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
635
636 MavenArchiver archiver = getMavenArchiver(jarArchiver);
637
638 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
639 config.setForced(true);
640 config.getManifest().setAddDefaultImplementationEntries(true);
641 config.getManifest().setAddDefaultSpecificationEntries(true);
642 config.getManifest().setMainClass("org.apache.maven.Foo");
643 config.getManifest().setAddClasspath(true);
644 config.getManifest().setClasspathLayoutType(ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM);
645 config.getManifest()
646 .setCustomClasspathLayout(
647 "${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}");
648 archiver.createArchive(session, project, config);
649 assertThat(jarFile).exists();
650 final Manifest manifest = getJarFileManifest(jarFile);
651 String classPath = manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
652 assertThat(classPath).isNotNull();
653 assertThat(classPath.split(" "))
654 .containsExactly("dummy1-1.0.jar", "dummy2-1.5.jar", "dummy3-2.0-classifier.jar");
655 }
656
657 private void deleteAndAssertNotPresent(File jarFile) {
658 jarFile.delete();
659 assertThat(jarFile).doesNotExist();
660 }
661
662 @Test
663 void testDefaultClassPathValueWithSnapshot() throws Exception {
664 MavenSession session = getDummySession();
665 MavenProject project = getDummyProjectWithSnapshot();
666 File jarFile = new File("target/test/dummy.jar");
667 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
668
669 MavenArchiver archiver = getMavenArchiver(jarArchiver);
670
671 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
672 config.setForced(true);
673 config.getManifest().setAddDefaultImplementationEntries(true);
674 config.getManifest().setAddDefaultSpecificationEntries(true);
675 config.getManifest().setMainClass("org.apache.maven.Foo");
676 config.getManifest().setAddClasspath(true);
677 config.getManifest().setClasspathLayoutType(ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM);
678 config.getManifest()
679 .setCustomClasspathLayout(
680 "${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}");
681 archiver.createArchive(session, project, config);
682 assertThat(jarFile).exists();
683
684 final Manifest manifest = getJarFileManifest(jarFile);
685 String classPath = manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
686 assertThat(classPath).isNotNull();
687 assertThat(classPath.split(" "))
688 .containsExactly("dummy1-1.1-20081022.112233-1.jar", "dummy2-1.5.jar", "dummy3-2.0-classifier.jar");
689 }
690
691 @Test
692 void testMavenRepoClassPathValue() throws Exception {
693 MavenSession session = getDummySession();
694 MavenProject project = getDummyProject();
695 File jarFile = new File("target/test/dummy.jar");
696 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
697
698 MavenArchiver archiver = getMavenArchiver(jarArchiver);
699
700 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
701 config.setForced(true);
702 config.getManifest().setAddDefaultImplementationEntries(true);
703 config.getManifest().setAddDefaultSpecificationEntries(true);
704 config.getManifest().setMainClass("org.apache.maven.Foo");
705 config.getManifest().setAddClasspath(true);
706 config.getManifest().setUseUniqueVersions(true);
707 config.getManifest().setClasspathLayoutType(ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_REPOSITORY);
708 archiver.createArchive(session, project, config);
709 assertThat(jarFile).exists();
710 Manifest manifest = archiver.getManifest(session, project, config);
711 String[] classPathEntries =
712 new String(manifest.getMainAttributes().getValue("Class-Path").getBytes()).split(" ");
713 assertThat(classPathEntries)
714 .containsExactly(
715 "org/apache/dummy/dummy1/1.0.1/dummy1-1.0.jar",
716 "org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
717 "org/apache/dummy/bar/dummy3/2.0/dummy3-2.0-classifier.jar");
718
719 String classPath = getJarFileManifest(jarFile).getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
720 assertThat(classPath).isNotNull();
721 assertThat(classPath.split(" "))
722 .containsExactly(
723 "org/apache/dummy/dummy1/1.0.1/dummy1-1.0.jar",
724 "org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
725 "org/apache/dummy/bar/dummy3/2.0/dummy3-2.0-classifier.jar");
726 }
727
728 @Test
729 void shouldCreateArchiveWithSimpleClassPathLayoutWhileSettingSimpleLayoutExplicit() throws Exception {
730 MavenSession session = getDummySession();
731 MavenProject project = getDummyProject();
732 File jarFile = new File("target/test/dummy-explicit-simple.jar");
733 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
734
735 MavenArchiver archiver = getMavenArchiver(jarArchiver);
736
737 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
738 config.setForced(true);
739 config.getManifest().setAddDefaultImplementationEntries(true);
740 config.getManifest().setAddDefaultSpecificationEntries(true);
741 config.getManifest().setMainClass("org.apache.maven.Foo");
742 config.getManifest().setAddClasspath(true);
743 config.getManifest().setClasspathPrefix("lib");
744 config.getManifest().setClasspathLayoutType(ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_SIMPLE);
745
746 archiver.createArchive(session, project, config);
747 assertThat(jarFile).exists();
748 Manifest manifest = archiver.getManifest(session, project, config);
749 String[] classPathEntries =
750 new String(manifest.getMainAttributes().getValue("Class-Path").getBytes()).split(" ");
751 assertThat(classPathEntries)
752 .containsExactly("lib/dummy1-1.0.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0-classifier.jar");
753
754 String classPath = getJarFileManifest(jarFile).getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
755
756 assertThat(classPath).isNotNull();
757 assertThat(classPath.split(" "))
758 .containsExactly("lib/dummy1-1.0.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0-classifier.jar");
759 }
760
761 @Test
762 void shouldCreateArchiveCustomerLayoutSimple() throws Exception {
763 MavenSession session = getDummySession();
764 MavenProject project = getDummyProject();
765 File jarFile = new File("target/test/dummy-custom-layout-simple.jar");
766 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
767
768 MavenArchiver archiver = getMavenArchiver(jarArchiver);
769
770 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
771 config.setForced(true);
772 config.getManifest().setAddDefaultImplementationEntries(true);
773 config.getManifest().setAddDefaultSpecificationEntries(true);
774 config.getManifest().setMainClass("org.apache.maven.Foo");
775 config.getManifest().setAddClasspath(true);
776 config.getManifest().setClasspathPrefix("lib");
777 config.getManifest().setClasspathLayoutType(ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM);
778 config.getManifest().setCustomClasspathLayout(MavenArchiver.SIMPLE_LAYOUT);
779
780 archiver.createArchive(session, project, config);
781 assertThat(jarFile).exists();
782 Manifest manifest = archiver.getManifest(session, project, config);
783 String[] classPathEntries =
784 new String(manifest.getMainAttributes().getValue("Class-Path").getBytes()).split(" ");
785 assertThat(classPathEntries)
786 .containsExactly("lib/dummy1-1.0.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0-classifier.jar");
787
788 String classPath = getJarFileManifest(jarFile).getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
789
790 assertThat(classPath).isNotNull();
791 assertThat(classPath.split(" "))
792 .containsExactly("lib/dummy1-1.0.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0-classifier.jar");
793 }
794
795 @Test
796 void shouldCreateArchiveCustomLayoutSimpleNonUnique() throws Exception {
797 MavenSession session = getDummySession();
798 MavenProject project = getDummyProject();
799 File jarFile = new File("target/test/dummy-custom-layout-simple-non-unique.jar");
800 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
801
802 MavenArchiver archiver = getMavenArchiver(jarArchiver);
803
804 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
805 config.setForced(true);
806 config.getManifest().setAddDefaultImplementationEntries(true);
807 config.getManifest().setAddDefaultSpecificationEntries(true);
808 config.getManifest().setMainClass("org.apache.maven.Foo");
809 config.getManifest().setAddClasspath(true);
810 config.getManifest().setClasspathPrefix("lib");
811 config.getManifest().setClasspathLayoutType(ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM);
812 config.getManifest().setCustomClasspathLayout(MavenArchiver.SIMPLE_LAYOUT_NONUNIQUE);
813
814 archiver.createArchive(session, project, config);
815 assertThat(jarFile).exists();
816 Manifest manifest = archiver.getManifest(session, project, config);
817 String[] classPathEntries =
818 new String(manifest.getMainAttributes().getValue("Class-Path").getBytes()).split(" ");
819 assertThat(classPathEntries)
820 .containsExactly("lib/dummy1-1.0.1.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0-classifier.jar");
821
822 String classPath = getJarFileManifest(jarFile).getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
823
824 assertThat(classPath).isNotNull();
825 assertThat(classPath.split(" "))
826 .containsExactly("lib/dummy1-1.0.1.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0-classifier.jar");
827 }
828
829 @Test
830 void shouldCreateArchiveCustomLayoutRepository() throws Exception {
831 MavenSession session = getDummySession();
832 MavenProject project = getDummyProject();
833 File jarFile = new File("target/test/dummy-custom-layout-repo.jar");
834 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
835
836 MavenArchiver archiver = getMavenArchiver(jarArchiver);
837
838 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
839 config.setForced(true);
840 config.getManifest().setAddDefaultImplementationEntries(true);
841 config.getManifest().setAddDefaultSpecificationEntries(true);
842 config.getManifest().setMainClass("org.apache.maven.Foo");
843 config.getManifest().setAddClasspath(true);
844 config.getManifest().setClasspathPrefix("lib");
845 config.getManifest().setClasspathLayoutType(ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM);
846 config.getManifest().setCustomClasspathLayout(MavenArchiver.REPOSITORY_LAYOUT);
847
848 archiver.createArchive(session, project, config);
849 assertThat(jarFile).exists();
850 Manifest manifest = archiver.getManifest(session, project, config);
851 String[] classPathEntries =
852 new String(manifest.getMainAttributes().getValue("Class-Path").getBytes()).split(" ");
853 assertThat(classPathEntries)
854 .containsExactly(
855 "lib/org/apache/dummy/dummy1/1.0.1/dummy1-1.0.jar",
856 "lib/org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
857 "lib/org/apache/dummy/bar/dummy3/2.0/dummy3-2.0-classifier.jar");
858
859 String classPath = getJarFileManifest(jarFile).getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
860
861 assertThat(classPath).isNotNull();
862 assertThat(classPath.split(" "))
863 .containsExactly(
864 "lib/org/apache/dummy/dummy1/1.0.1/dummy1-1.0.jar",
865 "lib/org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
866 "lib/org/apache/dummy/bar/dummy3/2.0/dummy3-2.0-classifier.jar");
867 }
868
869 @Test
870 void shouldCreateArchiveCustomLayoutRepositoryNonUnique() throws Exception {
871 MavenSession session = getDummySession();
872 MavenProject project = getDummyProject();
873 File jarFile = new File("target/test/dummy-custom-layout-repo-non-unique.jar");
874 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
875
876 MavenArchiver archiver = getMavenArchiver(jarArchiver);
877
878 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
879 config.setForced(true);
880 config.getManifest().setAddDefaultImplementationEntries(true);
881 config.getManifest().setAddDefaultSpecificationEntries(true);
882 config.getManifest().setMainClass("org.apache.maven.Foo");
883 config.getManifest().setAddClasspath(true);
884 config.getManifest().setClasspathPrefix("lib");
885 config.getManifest().setClasspathLayoutType(ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM);
886 config.getManifest().setCustomClasspathLayout(MavenArchiver.REPOSITORY_LAYOUT_NONUNIQUE);
887
888 archiver.createArchive(session, project, config);
889 assertThat(jarFile).exists();
890 Manifest manifest = archiver.getManifest(session, project, config);
891 String[] classPathEntries =
892 new String(manifest.getMainAttributes().getValue("Class-Path").getBytes()).split(" ");
893 assertThat(classPathEntries)
894 .containsExactly(
895 "lib/org/apache/dummy/dummy1/1.0.1/dummy1-1.0.1.jar",
896 "lib/org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
897 "lib/org/apache/dummy/bar/dummy3/2.0/dummy3-2.0-classifier.jar");
898
899 String classPath = getJarFileManifest(jarFile).getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
900
901 assertThat(classPath).isNotNull();
902 assertThat(classPath.split(" "))
903 .containsExactly(
904 "lib/org/apache/dummy/dummy1/1.0.1/dummy1-1.0.1.jar",
905 "lib/org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
906 "lib/org/apache/dummy/bar/dummy3/2.0/dummy3-2.0-classifier.jar");
907 }
908
909 @Test
910 void shouldCreateArchiveWithSimpleClassPathLayoutUsingDefaults() throws Exception {
911 MavenSession session = getDummySession();
912 MavenProject project = getDummyProject();
913 File jarFile = new File("target/test/dummy-defaults.jar");
914 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
915
916 MavenArchiver archiver = getMavenArchiver(jarArchiver);
917
918 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
919 config.setForced(true);
920 config.getManifest().setAddDefaultImplementationEntries(true);
921 config.getManifest().setAddDefaultSpecificationEntries(true);
922 config.getManifest().setMainClass("org.apache.maven.Foo");
923 config.getManifest().setAddClasspath(true);
924 config.getManifest().setClasspathPrefix("lib");
925
926 archiver.createArchive(session, project, config);
927 assertThat(jarFile).exists();
928 Manifest manifest = archiver.getManifest(session, project, config);
929 String[] classPathEntries =
930 new String(manifest.getMainAttributes().getValue("Class-Path").getBytes()).split(" ");
931 assertThat(classPathEntries)
932 .containsExactly("lib/dummy1-1.0.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0-classifier.jar");
933
934 String classPath = getJarFileManifest(jarFile).getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
935 assertThat(classPath).isNotNull();
936 assertThat(classPath.split(" "))
937 .containsExactly("lib/dummy1-1.0.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0-classifier.jar");
938 }
939
940 @Test
941 void testMavenRepoClassPathValueWithSnapshot() throws Exception {
942 MavenSession session = getDummySession();
943 MavenProject project = getDummyProjectWithSnapshot();
944 File jarFile = new File("target/test/dummy.jar");
945 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
946
947 MavenArchiver archiver = getMavenArchiver(jarArchiver);
948
949 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
950 config.setForced(true);
951 config.getManifest().setAddDefaultImplementationEntries(true);
952 config.getManifest().setAddDefaultSpecificationEntries(true);
953 config.getManifest().setMainClass("org.apache.maven.Foo");
954 config.getManifest().setAddClasspath(true);
955 config.getManifest().setClasspathLayoutType(ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_REPOSITORY);
956 archiver.createArchive(session, project, config);
957 assertThat(jarFile).exists();
958
959 Manifest manifest = archiver.getManifest(session, project, config);
960 String[] classPathEntries =
961 new String(manifest.getMainAttributes().getValue("Class-Path").getBytes()).split(" ");
962 assertThat(classPathEntries)
963 .containsExactly(
964 "org/apache/dummy/dummy1/1.1-SNAPSHOT/dummy1-1.1-20081022.112233-1.jar",
965 "org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
966 "org/apache/dummy/bar/dummy3/2.0/dummy3-2.0-classifier.jar");
967
968 String classPath = getJarFileManifest(jarFile).getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
969 assertThat(classPath).isNotNull();
970 assertThat(classPath.split(" "))
971 .containsExactly(
972 "org/apache/dummy/dummy1/1.1-SNAPSHOT/dummy1-1.1-20081022.112233-1.jar",
973 "org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
974 "org/apache/dummy/bar/dummy3/2.0/dummy3-2.0-classifier.jar");
975 }
976
977 @Test
978 void testCustomClassPathValue() throws Exception {
979 MavenSession session = getDummySession();
980 MavenProject project = getDummyProject();
981 File jarFile = new File("target/test/dummy.jar");
982 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
983
984 MavenArchiver archiver = getMavenArchiver(jarArchiver);
985
986 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
987 config.setForced(true);
988 config.getManifest().setAddDefaultImplementationEntries(true);
989 config.getManifest().setAddDefaultSpecificationEntries(true);
990 config.getManifest().setMainClass("org.apache.maven.Foo");
991 config.getManifest().setAddClasspath(true);
992 config.getManifest().setClasspathLayoutType(ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM);
993 config.getManifest()
994 .setCustomClasspathLayout(
995 "${artifact.groupIdPath}/${artifact.artifactId}/${artifact.version}/TEST-${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}");
996 archiver.createArchive(session, project, config);
997 assertThat(jarFile).exists();
998 Manifest manifest = archiver.getManifest(session, project, config);
999 String[] classPathEntries =
1000 new String(manifest.getMainAttributes().getValue("Class-Path").getBytes()).split(" ");
1001 assertThat(classPathEntries)
1002 .containsExactly(
1003 "org/apache/dummy/dummy1/1.0/TEST-dummy1-1.0.jar",
1004 "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar",
1005 "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0-classifier.jar");
1006
1007 final Manifest manifest1 = getJarFileManifest(jarFile);
1008 String classPath = manifest1.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
1009 assertThat(classPath).isNotNull();
1010 assertThat(classPath.split(" "))
1011 .containsExactly(
1012 "org/apache/dummy/dummy1/1.0/TEST-dummy1-1.0.jar",
1013 "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar",
1014 "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0-classifier.jar");
1015 }
1016
1017 @Test
1018 void testCustomClassPathValueWithSnapshotResolvedVersion() throws Exception {
1019 MavenSession session = getDummySession();
1020 MavenProject project = getDummyProjectWithSnapshot();
1021 File jarFile = new File("target/test/dummy.jar");
1022 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
1023 MavenArchiver archiver = getMavenArchiver(jarArchiver);
1024
1025 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
1026 config.setForced(true);
1027 config.getManifest().setAddDefaultImplementationEntries(true);
1028 config.getManifest().setAddDefaultSpecificationEntries(true);
1029 config.getManifest().setMainClass("org.apache.maven.Foo");
1030 config.getManifest().setAddClasspath(true);
1031 config.getManifest().setClasspathLayoutType(ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM);
1032 config.getManifest()
1033 .setCustomClasspathLayout(
1034 "${artifact.groupIdPath}/${artifact.artifactId}/${artifact.baseVersion}/TEST-${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}");
1035 archiver.createArchive(session, project, config);
1036 assertThat(jarFile).exists();
1037
1038 Manifest manifest = archiver.getManifest(session, project, config);
1039 String[] classPathEntries =
1040 new String(manifest.getMainAttributes().getValue("Class-Path").getBytes()).split(" ");
1041 assertThat(classPathEntries)
1042 .containsExactly(
1043 "org/apache/dummy/dummy1/1.1-SNAPSHOT/TEST-dummy1-1.1-20081022.112233-1.jar",
1044 "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar",
1045 "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0-classifier.jar");
1046
1047 String classPath = getJarFileManifest(jarFile).getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
1048 assertThat(classPath).isNotNull();
1049 assertThat(classPath.split(" "))
1050 .containsExactly(
1051 "org/apache/dummy/dummy1/1.1-SNAPSHOT/TEST-dummy1-1.1-20081022.112233-1.jar",
1052 "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar",
1053 "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0-classifier.jar");
1054 }
1055
1056 @Test
1057 void testCustomClassPathValueWithSnapshotForcingBaseVersion() throws Exception {
1058 MavenSession session = getDummySession();
1059 MavenProject project = getDummyProjectWithSnapshot();
1060 File jarFile = new File("target/test/dummy.jar");
1061 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
1062
1063 MavenArchiver archiver = getMavenArchiver(jarArchiver);
1064
1065 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
1066 config.setForced(true);
1067 config.getManifest().setAddDefaultImplementationEntries(true);
1068 config.getManifest().setAddDefaultSpecificationEntries(true);
1069 config.getManifest().setMainClass("org.apache.maven.Foo");
1070 config.getManifest().setAddClasspath(true);
1071 config.getManifest().setClasspathLayoutType(ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM);
1072 config.getManifest()
1073 .setCustomClasspathLayout(
1074 "${artifact.groupIdPath}/${artifact.artifactId}/${artifact.baseVersion}/TEST-${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}");
1075 archiver.createArchive(session, project, config);
1076 assertThat(jarFile).exists();
1077 Manifest manifest = archiver.getManifest(session, project, config);
1078 String[] classPathEntries =
1079 new String(manifest.getMainAttributes().getValue("Class-Path").getBytes()).split(" ");
1080 assertThat(classPathEntries[0]).isEqualTo("org/apache/dummy/dummy1/1.1-SNAPSHOT/TEST-dummy1-1.1-SNAPSHOT.jar");
1081 assertThat(classPathEntries[1]).isEqualTo("org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar");
1082 assertThat(classPathEntries[2]).isEqualTo("org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0-classifier.jar");
1083
1084 String classPath = getJarFileManifest(jarFile).getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
1085 assertThat(classPath).isNotNull();
1086 assertThat(classPath.split(" "))
1087 .containsExactly(
1088 "org/apache/dummy/dummy1/1.1-SNAPSHOT/TEST-dummy1-1.1-SNAPSHOT.jar",
1089 "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar",
1090 "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0-classifier.jar");
1091 }
1092
1093 @Test
1094 void testDefaultPomProperties() throws Exception {
1095 MavenSession session = getDummySession();
1096 MavenProject project = getDummyProject();
1097 File jarFile = new File("target/test/dummy.jar");
1098 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
1099
1100 MavenArchiver archiver = getMavenArchiver(jarArchiver);
1101
1102 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
1103 config.setForced(true);
1104 archiver.createArchive(session, project, config);
1105 assertThat(jarFile).exists();
1106
1107 final String groupId = project.getGroupId();
1108 final String artifactId = project.getArtifactId();
1109 final String version = project.getVersion();
1110
1111 JarFile virtJarFile = new JarFile(jarFile);
1112 ZipEntry pomPropertiesEntry =
1113 virtJarFile.getEntry("META-INF/maven/" + groupId + "/" + artifactId + "/pom.properties");
1114 assertThat(pomPropertiesEntry).isNotNull();
1115
1116 try (InputStream is = virtJarFile.getInputStream(pomPropertiesEntry)) {
1117 Properties p = new Properties();
1118 p.load(is);
1119
1120 assertThat(p.getProperty("groupId")).isEqualTo(groupId);
1121 assertThat(p.getProperty("artifactId")).isEqualTo(artifactId);
1122 assertThat(p.getProperty("version")).isEqualTo(version);
1123 }
1124 virtJarFile.close();
1125 }
1126
1127 @Test
1128 void testCustomPomProperties() throws Exception {
1129 MavenSession session = getDummySession();
1130 MavenProject project = getDummyProject();
1131 File jarFile = new File("target/test/dummy.jar");
1132 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
1133
1134 MavenArchiver archiver = getMavenArchiver(jarArchiver);
1135
1136 File customPomPropertiesFile = new File("src/test/resources/custom-pom.properties");
1137 MavenArchiveConfiguration config = new MavenArchiveConfiguration();
1138 config.setForced(true);
1139 config.setPomPropertiesFile(customPomPropertiesFile);
1140 archiver.createArchive(session, project, config);
1141 assertThat(jarFile).exists();
1142
1143 final String groupId = project.getGroupId();
1144 final String artifactId = project.getArtifactId();
1145 final String version = project.getVersion();
1146
1147 try (JarFile virtJarFile = new JarFile(jarFile)) {
1148 ZipEntry pomPropertiesEntry =
1149 virtJarFile.getEntry("META-INF/maven/" + groupId + "/" + artifactId + "/pom.properties");
1150 assertThat(pomPropertiesEntry).isNotNull();
1151
1152 try (InputStream is = virtJarFile.getInputStream(pomPropertiesEntry)) {
1153 Properties p = new Properties();
1154 p.load(is);
1155
1156 assertThat(p.getProperty("groupId")).isEqualTo(groupId);
1157 assertThat(p.getProperty("artifactId")).isEqualTo(artifactId);
1158 assertThat(p.getProperty("version")).isEqualTo(version);
1159 assertThat(p.getProperty("build.revision")).isEqualTo("1337");
1160 assertThat(p.getProperty("build.branch")).isEqualTo("tags/0.1.1");
1161 }
1162 }
1163 }
1164
1165 private JarArchiver getCleanJarArchiver(File jarFile) {
1166 deleteAndAssertNotPresent(jarFile);
1167 JarArchiver jarArchiver = new JarArchiver();
1168 jarArchiver.setDestFile(jarFile);
1169 return jarArchiver;
1170 }
1171
1172
1173
1174
1175
1176 private MavenProject getDummyProject() throws Exception {
1177 MavenProject project = getMavenProject();
1178
1179 Artifact artifact = mock(Artifact.class);
1180 when(artifact.getGroupId()).thenReturn("org.apache.dummy");
1181 when(artifact.getArtifactId()).thenReturn("dummy");
1182 when(artifact.getVersion()).thenReturn("0.1.1");
1183 when(artifact.getBaseVersion()).thenReturn("0.1.2");
1184 when(artifact.getSelectedVersion()).thenReturn(new DefaultArtifactVersion("0.1.1"));
1185 when(artifact.getType()).thenReturn("jar");
1186 when(artifact.getArtifactHandler()).thenReturn(new DefaultArtifactHandler("jar"));
1187 project.setArtifact(artifact);
1188
1189 Set<Artifact> artifacts = getArtifacts(getMockArtifact1Release(), getMockArtifact2(), getMockArtifact3());
1190 project.setArtifacts(artifacts);
1191
1192 return project;
1193 }
1194
1195 private MavenProject getMavenProject() {
1196 Model model = new Model();
1197 model.setGroupId("org.apache.dummy");
1198 model.setArtifactId("dummy");
1199 model.setVersion("0.1.1");
1200
1201 final MavenProject project = new MavenProject(model);
1202 project.setRemoteArtifactRepositories(Collections.emptyList());
1203 project.setPluginArtifactRepositories(Collections.emptyList());
1204 project.setName("archiver test");
1205
1206 File pomFile = new File("src/test/resources/pom.xml");
1207 project.setFile(pomFile);
1208
1209 Build build = new Build();
1210 build.setDirectory("target");
1211 build.setOutputDirectory("target");
1212 project.setBuild(build);
1213
1214 Organization organization = new Organization();
1215 organization.setName("Apache");
1216 project.setOrganization(organization);
1217 return project;
1218 }
1219
1220 private Artifact getMockArtifact3() {
1221 Artifact artifact = mock(Artifact.class);
1222 when(artifact.getGroupId()).thenReturn("org.apache.dummy.bar");
1223 when(artifact.getArtifactId()).thenReturn("dummy3");
1224 when(artifact.getVersion()).thenReturn("2.0");
1225 when(artifact.getType()).thenReturn("jar");
1226 when(artifact.getScope()).thenReturn("runtime");
1227 when(artifact.getClassifier()).thenReturn("classifier");
1228 File file = getClasspathFile(artifact.getArtifactId() + "-" + artifact.getVersion() + ".jar");
1229 when(artifact.getFile()).thenReturn(file);
1230 ArtifactHandler artifactHandler = mock(ArtifactHandler.class);
1231 when(artifactHandler.isAddedToClasspath()).thenReturn(true);
1232 when(artifactHandler.getExtension()).thenReturn("jar");
1233 when(artifact.getArtifactHandler()).thenReturn(artifactHandler);
1234 return artifact;
1235 }
1236
1237 private MavenProject getDummyProjectWithSnapshot() throws Exception {
1238 MavenProject project = getMavenProject();
1239
1240 Artifact artifact = mock(Artifact.class);
1241 when(artifact.getGroupId()).thenReturn("org.apache.dummy");
1242 when(artifact.getArtifactId()).thenReturn("dummy");
1243 when(artifact.getVersion()).thenReturn("0.1.1");
1244 when(artifact.getBaseVersion()).thenReturn("0.1.1");
1245 when(artifact.getSelectedVersion()).thenReturn(new DefaultArtifactVersion("0.1.1"));
1246 when(artifact.getType()).thenReturn("jar");
1247 when(artifact.getScope()).thenReturn("compile");
1248 when(artifact.getArtifactHandler()).thenReturn(new DefaultArtifactHandler("jar"));
1249 project.setArtifact(artifact);
1250
1251 Set<Artifact> artifacts = getArtifacts(getMockArtifact1(), getMockArtifact2(), getMockArtifact3());
1252 project.setArtifacts(artifacts);
1253
1254 return project;
1255 }
1256
1257 private Artifact getMockArtifact2() {
1258 Artifact artifact = mock(Artifact.class);
1259 when(artifact.getGroupId()).thenReturn("org.apache.dummy.foo");
1260 when(artifact.getArtifactId()).thenReturn("dummy2");
1261 when(artifact.getVersion()).thenReturn("1.5");
1262 when(artifact.getType()).thenReturn("jar");
1263 when(artifact.getScope()).thenReturn("runtime");
1264 File file = getClasspathFile(artifact.getArtifactId() + "-" + artifact.getVersion() + ".jar");
1265 when(artifact.getFile()).thenReturn(file);
1266 ArtifactHandler artifactHandler = mock(ArtifactHandler.class);
1267 when(artifactHandler.isAddedToClasspath()).thenReturn(true);
1268 when(artifactHandler.getExtension()).thenReturn("jar");
1269 when(artifact.getArtifactHandler()).thenReturn(artifactHandler);
1270 return artifact;
1271 }
1272
1273 private Artifact getArtifactWithDot() {
1274 Artifact artifact = mock(Artifact.class);
1275 when(artifact.getGroupId()).thenReturn("org.apache.dummy.foo");
1276 when(artifact.getArtifactId()).thenReturn("dummy.dot");
1277 when(artifact.getVersion()).thenReturn("1.5");
1278 when(artifact.getScope()).thenReturn("runtime");
1279 when(artifact.getArtifactHandler()).thenReturn(new DefaultArtifactHandler("jar"));
1280 return artifact;
1281 }
1282
1283 private Artifact getMockArtifact1() {
1284 Artifact artifact = mock(Artifact.class);
1285 when(artifact.getGroupId()).thenReturn("org.apache.dummy");
1286 when(artifact.getArtifactId()).thenReturn("dummy1");
1287 when(artifact.getVersion()).thenReturn("1.1-20081022.112233-1");
1288 when(artifact.getBaseVersion()).thenReturn("1.1-SNAPSHOT");
1289 when(artifact.getType()).thenReturn("jar");
1290 when(artifact.getScope()).thenReturn("runtime");
1291 File file = getClasspathFile(artifact.getArtifactId() + "-" + artifact.getVersion() + ".jar");
1292 when(artifact.getFile()).thenReturn(file);
1293 ArtifactHandler artifactHandler = mock(ArtifactHandler.class);
1294 when(artifactHandler.isAddedToClasspath()).thenReturn(true);
1295 when(artifactHandler.getExtension()).thenReturn("jar");
1296 when(artifact.getArtifactHandler()).thenReturn(artifactHandler);
1297 return artifact;
1298 }
1299
1300 private Artifact getMockArtifact1Release() {
1301 Artifact artifact = mock(Artifact.class);
1302 when(artifact.getGroupId()).thenReturn("org.apache.dummy");
1303 when(artifact.getArtifactId()).thenReturn("dummy1");
1304 when(artifact.getVersion()).thenReturn("1.0");
1305 when(artifact.getBaseVersion()).thenReturn("1.0.1");
1306 when(artifact.getType()).thenReturn("jar");
1307 when(artifact.getScope()).thenReturn("runtime");
1308 File file = getClasspathFile(artifact.getArtifactId() + "-" + artifact.getVersion() + ".jar");
1309 when(artifact.getFile()).thenReturn(file);
1310 ArtifactHandler artifactHandler = mock(ArtifactHandler.class);
1311 when(artifactHandler.isAddedToClasspath()).thenReturn(true);
1312 when(artifactHandler.getExtension()).thenReturn("jar");
1313 when(artifact.getArtifactHandler()).thenReturn(artifactHandler);
1314 return artifact;
1315 }
1316
1317 private File getClasspathFile(String file) {
1318 URL resource = Thread.currentThread().getContextClassLoader().getResource(file);
1319 if (resource == null) {
1320 throw new IllegalStateException(
1321 "Cannot retrieve java.net.URL for file: " + file + " on the current test classpath.");
1322 }
1323
1324 URI uri = new File(resource.getPath()).toURI().normalize();
1325
1326 return new File(uri.getPath().replaceAll("%20", " "));
1327 }
1328
1329 private MavenSession getDummySession() {
1330 Properties systemProperties = new Properties();
1331 systemProperties.put("maven.version", "3.1.1");
1332 systemProperties.put(
1333 "maven.build.version",
1334 "Apache Maven 3.1.1 (0728685237757ffbf44136acec0402957f723d9a; 2013-09-17 17:22:22+0200)");
1335
1336 return getDummySession(systemProperties);
1337 }
1338
1339 private MavenSession getDummySessionWithoutMavenVersion() {
1340 return getDummySession(new Properties());
1341 }
1342
1343 private MavenSession getDummySession(Properties systemProperties) {
1344 MavenSession session = mock(MavenSession.class);
1345 when(session.getSystemProperties()).thenReturn(systemProperties);
1346 return session;
1347 }
1348
1349 private Set<Artifact> getArtifacts(Artifact... artifacts) {
1350 Set<Artifact> result = new TreeSet<>(new ArtifactComparator());
1351 result.addAll(Arrays.asList(artifacts));
1352 return result;
1353 }
1354
1355 public Manifest getJarFileManifest(File jarFile) throws IOException {
1356 try (JarFile jar = new JarFile(jarFile)) {
1357 return jar.getManifest();
1358 }
1359 }
1360
1361 @Test
1362 void testParseOutputTimestamp() {
1363 assertThat(parseBuildOutputTimestamp(null)).isEmpty();
1364 assertThat(parseBuildOutputTimestamp("")).isEmpty();
1365 assertThat(parseBuildOutputTimestamp(".")).isEmpty();
1366 assertThat(parseBuildOutputTimestamp(" ")).isEmpty();
1367 assertThat(parseBuildOutputTimestamp("_")).isEmpty();
1368 assertThat(parseBuildOutputTimestamp("-")).isEmpty();
1369 assertThat(parseBuildOutputTimestamp("/")).isEmpty();
1370 assertThat(parseBuildOutputTimestamp("!")).isEmpty();
1371 assertThat(parseBuildOutputTimestamp("*")).isEmpty();
1372
1373 assertThat(parseBuildOutputTimestamp("1570300662").get().getEpochSecond())
1374 .isEqualTo(1570300662L);
1375 assertThat(parseBuildOutputTimestamp("2019-10-05T18:37:42Z").get().getEpochSecond())
1376 .isEqualTo(1570300662L);
1377 assertThat(parseBuildOutputTimestamp("2019-10-05T20:37:42+02:00").get().getEpochSecond())
1378 .isEqualTo(1570300662L);
1379 assertThat(parseBuildOutputTimestamp("2019-10-05T16:37:42-02:00").get().getEpochSecond())
1380 .isEqualTo(1570300662L);
1381
1382
1383
1384
1385
1386 assertThatExceptionOfType(IllegalArgumentException.class)
1387 .isThrownBy(() -> parseBuildOutputTimestamp("2019-10-05T20:37:42+0200"));
1388 assertThatExceptionOfType(IllegalArgumentException.class)
1389 .isThrownBy(() -> parseBuildOutputTimestamp("2019-10-05T20:37:42-0200"));
1390 }
1391
1392 @ParameterizedTest
1393 @NullAndEmptySource
1394 @ValueSource(strings = {".", " ", "_", "-", "T", "/", "!", "!", "*", "ñ"})
1395 void testEmptyParseOutputTimestampInstant(String value) {
1396
1397 assertThat(parseBuildOutputTimestamp(value)).isEmpty();
1398 }
1399
1400 @ParameterizedTest
1401 @CsvSource({
1402 "1570300662,1570300662",
1403 "2147483648,2147483648",
1404 "2019-10-05T18:37:42Z,1570300662",
1405 "2019-10-05T20:37:42+02:00,1570300662",
1406 "2019-10-05T16:37:42-02:00,1570300662",
1407 "1988-02-22T15:23:47.76598Z,572541827",
1408 "2011-12-03T10:15:30+01:00,1322903730",
1409 "1980-01-01T00:00:02Z,315532802",
1410 "2099-12-31T23:59:59Z,4102444799"
1411 })
1412 void testParseOutputTimestampInstant(String value, long expected) {
1413 assertThat(parseBuildOutputTimestamp(value)).contains(Instant.ofEpochSecond(expected));
1414 }
1415
1416 @ParameterizedTest
1417 @ValueSource(
1418 strings = {
1419 "2019-10-05T20:37:42+0200",
1420 "2019-10-05T20:37:42-0200",
1421 "2019-10-05T25:00:00Z",
1422 "2019-10-05",
1423 "XYZ",
1424 "Tue, 3 Jun 2008 11:05:30 GMT",
1425 "2011-12-03T10:15:30+01:00[Europe/Paris]"
1426 })
1427 void testThrownParseOutputTimestampInstant(String outputTimestamp) {
1428
1429 assertThatExceptionOfType(IllegalArgumentException.class)
1430 .isThrownBy(() -> parseBuildOutputTimestamp(outputTimestamp))
1431 .withCauseInstanceOf(DateTimeParseException.class);
1432 }
1433
1434 @ParameterizedTest
1435 @CsvSource({
1436 "2011-12-03T10:15:30+01,1322903730",
1437 "2019-10-05T20:37:42+02,1570300662",
1438 "2011-12-03T10:15:30+06,1322885730",
1439 "1988-02-22T20:37:42+06,572539062"
1440 })
1441 @EnabledForJreRange(min = JRE.JAVA_9)
1442 void testShortOffset(String value, long expected) {
1443 assertThat(parseBuildOutputTimestamp(value)).contains(Instant.ofEpochSecond(expected));
1444 }
1445
1446 private long testReproducibleJarEntryTime(String name, String timestamp) throws Exception {
1447 File jarFile = new File("target/test/dummy-" + name + ".jar");
1448
1449 MavenArchiver archiver = getMavenArchiver(getCleanJarArchiver(jarFile));
1450 archiver.configureReproducibleBuild(timestamp);
1451 archiver.createArchive(getDummySession(), getDummyProject(), new MavenArchiveConfiguration());
1452
1453 assertThat(jarFile).exists();
1454 ZipFile zf = new ZipFile(jarFile);
1455 ZipEntry ze = zf.getEntry("META-INF/MANIFEST.MF");
1456 return ze.getTime();
1457 }
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469 @Test
1470 void testReproducibleJar19700101() throws Exception {
1471 long entryTime = testReproducibleJarEntryTime("1970", "10");
1472 assertThat(entryTime).isGreaterThanOrEqualTo(0);
1473 }
1474
1475 private void checkJar(String name, String timestamp) throws Exception {
1476 File jarFile = new File("target/test/dummy-" + name + ".jar");
1477 JarArchiver jarArchiver = getCleanJarArchiver(jarFile);
1478
1479 MavenArchiver archiver = getMavenArchiver(jarArchiver);
1480 archiver.configureReproducibleBuild(timestamp);
1481
1482 MavenSession session = getDummySession();
1483 MavenProject project = getDummyProject();
1484
1485 archiver.createArchive(session, project, new MavenArchiveConfiguration());
1486 assertThat(jarFile).exists();
1487 }
1488
1489 @Test
1490 void checkJar() throws Exception {
1491 checkJar("1970", "10");
1492 checkJar("1970-0h0m10", "1970-01-01T00:00:10Z");
1493 checkJar("1970-2h", "1970-01-01T02:00:00Z");
1494 checkJar("1970-1h59", "1970-01-01T01:59:00Z");
1495 checkJar("1970-1h", "1970-01-01T01:00:00Z");
1496 checkJar("1970-0h59", "1970-01-01T00:59:00Z");
1497 checkJar("2000", "2000-01-01T00:00:00Z");
1498 }
1499
1500 @Test
1501 void testCompress() throws Exception {
1502 File zipFile = new File("target/test/dummy.zip");
1503 ZipArchiveOutputStream zipArchiveOutputStream =
1504 new ZipArchiveOutputStream(bufferedOutputStream(fileOutputStream(zipFile, "zip")));
1505 zipArchiveOutputStream.setEncoding("UTF-8");
1506 zipArchiveOutputStream.setCreateUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy.NEVER);
1507 zipArchiveOutputStream.setMethod(ZipArchiveOutputStream.DEFLATED);
1508
1509 ZipArchiveEntry ze = new ZipArchiveEntry("f.txt");
1510 ze.setTime(0);
1511
1512 zipArchiveOutputStream.putArchiveEntry(ze);
1513 zipArchiveOutputStream.write(1);
1514 zipArchiveOutputStream.closeArchiveEntry();
1515
1516 zipArchiveOutputStream.close();
1517
1518 assertTrue(zipFile.delete());
1519 }
1520 }