View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.dependency.fromConfiguration;
20  
21  import javax.inject.Inject;
22  
23  import java.io.File;
24  import java.io.IOException;
25  import java.nio.file.Files;
26  import java.nio.file.attribute.FileTime;
27  import java.util.ArrayList;
28  import java.util.Collection;
29  import java.util.Collections;
30  import java.util.List;
31  
32  import org.apache.maven.api.plugin.testing.Basedir;
33  import org.apache.maven.api.plugin.testing.InjectMojo;
34  import org.apache.maven.api.plugin.testing.MojoExtension;
35  import org.apache.maven.api.plugin.testing.MojoParameter;
36  import org.apache.maven.api.plugin.testing.MojoTest;
37  import org.apache.maven.artifact.Artifact;
38  import org.apache.maven.artifact.versioning.VersionRange;
39  import org.apache.maven.execution.MavenSession;
40  import org.apache.maven.model.Dependency;
41  import org.apache.maven.model.DependencyManagement;
42  import org.apache.maven.plugin.MojoExecutionException;
43  import org.apache.maven.plugins.dependency.testUtils.DependencyArtifactStubFactory;
44  import org.apache.maven.plugins.dependency.utils.markers.UnpackFileMarkerHandler;
45  import org.apache.maven.project.MavenProject;
46  import org.codehaus.plexus.archiver.manager.ArchiverManager;
47  import org.junit.jupiter.api.BeforeEach;
48  import org.junit.jupiter.api.Test;
49  import org.junit.jupiter.api.io.TempDir;
50  
51  import static org.junit.jupiter.api.Assertions.assertEquals;
52  import static org.junit.jupiter.api.Assertions.assertNotEquals;
53  import static org.junit.jupiter.api.Assertions.assertTrue;
54  import static org.junit.jupiter.api.Assertions.fail;
55  
56  @MojoTest(realRepositorySession = true)
57  @Basedir("/unit/unpack-dependencies-test")
58  class TestUnpackMojo {
59  
60      @TempDir
61      private File tempDir;
62  
63      private DependencyArtifactStubFactory stubFactory;
64  
65      @Inject
66      private MavenSession session;
67  
68      @Inject
69      private MavenProject project;
70  
71      @Inject
72      private ArchiverManager archiverManager;
73  
74      @BeforeEach
75      void setUp() throws Exception {
76          stubFactory = new DependencyArtifactStubFactory(tempDir, true, false);
77          stubFactory.setUnpackableFile(archiverManager);
78          stubFactory.setSrcFile(MojoExtension.getTestFile("test.txt"));
79  
80          session.getRequest().setLocalRepositoryPath(new File(tempDir, "localTestRepo"));
81  
82          project.getBuild().setDirectory(new File(tempDir, "target").getAbsolutePath());
83      }
84  
85      private ArtifactItem getSingleArtifactItem(UnpackMojo mojo) throws MojoExecutionException {
86          List<ArtifactItem> list = mojo.getProcessedArtifactItems(false);
87          return list.get(0);
88      }
89  
90      @Test
91      @InjectMojo(goal = "unpack")
92      void testGetArtifactItems(UnpackMojo mojo) throws Exception {
93  
94          ArtifactItem item = new ArtifactItem();
95  
96          item.setArtifactId("artifact");
97          item.setGroupId("groupId");
98          item.setVersion("1.0");
99  
100         ArrayList<ArtifactItem> list = new ArrayList<>(1);
101         list.add(createArtifact(item));
102 
103         mojo.setArtifactItems(list);
104 
105         ArtifactItem result = getSingleArtifactItem(mojo);
106         assertEquals(mojo.getOutputDirectory(), result.getOutputDirectory());
107 
108         File output = new File(mojo.getOutputDirectory(), "override");
109         item.setOutputDirectory(output);
110         result = getSingleArtifactItem(mojo);
111         assertEquals(output, result.getOutputDirectory());
112     }
113 
114     private void assertMarkerFiles(UnpackMojo mojo, Collection<ArtifactItem> items, boolean exists) {
115         for (ArtifactItem item : items) {
116             assertMarkerFile(mojo, exists, item);
117         }
118     }
119 
120     private void assertMarkerFile(UnpackMojo mojo, boolean exists, ArtifactItem item) {
121         UnpackFileMarkerHandler handle = new UnpackFileMarkerHandler(item, mojo.getMarkersDirectory());
122         try {
123             assertEquals(exists, handle.isMarkerSet());
124         } catch (MojoExecutionException e) {
125             fail(e.getLongMessage());
126         }
127     }
128 
129     @Test
130     @InjectMojo(goal = "unpack")
131     void testUnpackFile(UnpackMojo mojo) throws Exception {
132         List<ArtifactItem> list = stubFactory.getArtifactItems(stubFactory.getClassifiedArtifacts());
133 
134         mojo.setArtifactItems(list);
135 
136         mojo.execute();
137 
138         assertMarkerFiles(mojo, list, true);
139     }
140 
141     @Test
142     @InjectMojo(goal = "unpack")
143     @MojoParameter(name = "skip", value = "true")
144     void testSkip(UnpackMojo mojo) throws Exception {
145         List<ArtifactItem> list = stubFactory.getArtifactItems(stubFactory.getClassifiedArtifacts());
146 
147         mojo.setArtifactItems(list);
148 
149         mojo.execute();
150 
151         assertMarkerFiles(mojo, list, false);
152     }
153 
154     @Test
155     @InjectMojo(goal = "unpack")
156     void testUnpackToLocation(UnpackMojo mojo) throws Exception {
157         List<ArtifactItem> list = stubFactory.getArtifactItems(stubFactory.getClassifiedArtifacts());
158         ArtifactItem item = list.get(0);
159         item.setOutputDirectory(new File(mojo.getOutputDirectory(), "testOverride"));
160 
161         mojo.setArtifactItems(list);
162 
163         mojo.execute();
164 
165         assertMarkerFiles(mojo, list, true);
166     }
167 
168     @Test
169     @InjectMojo(goal = "unpack")
170     void testUnpackToLocationWhereLocationCannotBeCreatedThrowsException(UnpackMojo mojo) throws Exception {
171         List<ArtifactItem> list = stubFactory.getArtifactItems(stubFactory.getClassifiedArtifacts());
172         ArtifactItem item = list.get(0);
173         item.setOutputDirectory(new File(mojo.getOutputDirectory(), "testOverride"));
174 
175         mojo.setArtifactItems(list);
176         final File currentFile = mojo.getOutputDirectory();
177 
178         // pretend that the output directory cannot be found event after mkdirs has been called by the mojo
179         // ifor instance in the case when the outputDirectory cannot be created because of permissions on the
180         // parent of the output directory
181         mojo.setOutputDirectory(new File(currentFile.getAbsolutePath()) {
182 
183             private static final long serialVersionUID = -8559876942040177020L;
184 
185             @Override
186             public boolean exists() {
187                 // this file will always report that it does not exist
188                 return false;
189             }
190         });
191         try {
192             mojo.execute();
193             fail("Expected Exception Here.");
194         } catch (MojoExecutionException e) {
195             // caught the expected exception.
196         }
197     }
198 
199     @Test
200     @InjectMojo(goal = "unpack")
201     void testMissingVersionNotFound(UnpackMojo mojo) throws Exception {
202         ArtifactItem item = new ArtifactItem();
203 
204         item.setArtifactId("artifactId");
205         item.setClassifier("");
206         item.setGroupId("groupId");
207         item.setType("type");
208 
209         List<ArtifactItem> list = new ArrayList<>();
210         list.add(item);
211         mojo.setArtifactItems(list);
212 
213         try {
214             mojo.execute();
215             fail("Expected Exception Here.");
216         } catch (MojoExecutionException e) {
217             // caught the expected exception.
218         }
219     }
220 
221     private List<Dependency> getDependencyList(ArtifactItem item) {
222         Dependency dep = new Dependency();
223         dep.setArtifactId(item.getArtifactId());
224         dep.setClassifier(item.getClassifier());
225         dep.setGroupId(item.getGroupId());
226         dep.setType(item.getType());
227         dep.setVersion("2.0-SNAPSHOT");
228 
229         Dependency dep2 = new Dependency();
230         dep2.setArtifactId(item.getArtifactId());
231         dep2.setClassifier("classifier");
232         dep2.setGroupId(item.getGroupId());
233         dep2.setType(item.getType());
234         dep2.setVersion("2.1");
235 
236         List<Dependency> list = new ArrayList<>(2);
237         list.add(dep2);
238         list.add(dep);
239 
240         return list;
241     }
242 
243     @Test
244     @InjectMojo(goal = "unpack")
245     void testMissingVersionFromDependencies(UnpackMojo mojo) throws Exception {
246         ArtifactItem item = new ArtifactItem();
247 
248         item.setArtifactId("artifactId");
249         item.setClassifier("");
250         item.setGroupId("groupId");
251         item.setType("jar");
252 
253         List<ArtifactItem> list = new ArrayList<>();
254         list.add(item);
255         mojo.setArtifactItems(list);
256 
257         MavenProject project = mojo.getProject();
258         project.setDependencies(createArtifacts(getDependencyList(item)));
259 
260         mojo.execute();
261         assertMarkerFile(mojo, true, item);
262         assertEquals("2.0-SNAPSHOT", item.getVersion());
263     }
264 
265     @Test
266     @InjectMojo(goal = "unpack")
267     void testMissingVersionFromDependenciesWithClassifier(UnpackMojo mojo) throws Exception {
268         ArtifactItem item = new ArtifactItem();
269 
270         item.setArtifactId("artifactId");
271         item.setClassifier("classifier");
272         item.setGroupId("groupId");
273         item.setType("war");
274 
275         List<ArtifactItem> list = new ArrayList<>();
276         list.add(item);
277         mojo.setArtifactItems(list);
278 
279         MavenProject project = mojo.getProject();
280         project.setDependencies(createArtifacts(getDependencyList(item)));
281 
282         mojo.execute();
283         assertMarkerFile(mojo, true, item);
284         assertEquals("2.1", item.getVersion());
285     }
286 
287     private List<Dependency> getDependencyMgtList(ArtifactItem item) {
288         Dependency dep = new Dependency();
289         dep.setArtifactId(item.getArtifactId());
290         dep.setClassifier(item.getClassifier());
291         dep.setGroupId(item.getGroupId());
292         dep.setType(item.getType());
293         dep.setVersion("3.0-SNAPSHOT");
294 
295         Dependency dep2 = new Dependency();
296         dep2.setArtifactId(item.getArtifactId());
297         dep2.setClassifier("classifier");
298         dep2.setGroupId(item.getGroupId());
299         dep2.setType(item.getType());
300         dep2.setVersion("3.1");
301 
302         List<Dependency> list = new ArrayList<>(2);
303         list.add(dep2);
304         list.add(dep);
305 
306         return list;
307     }
308 
309     @Test
310     @InjectMojo(goal = "unpack")
311     void testMissingVersionFromDependencyMgt(UnpackMojo mojo) throws Exception {
312         ArtifactItem item = new ArtifactItem();
313 
314         item.setArtifactId("artifactId");
315         item.setClassifier("");
316         item.setGroupId("groupId");
317         item.setType("jar");
318 
319         MavenProject project = mojo.getProject();
320         project.setDependencies(createArtifacts(getDependencyList(item)));
321 
322         item = new ArtifactItem();
323 
324         item.setArtifactId("artifactId-2");
325         item.setClassifier("");
326         item.setGroupId("groupId");
327         item.setType("jar");
328 
329         List<ArtifactItem> list = new ArrayList<>();
330         list.add(item);
331 
332         mojo.setArtifactItems(list);
333 
334         DependencyManagement dependencyManagement = new DependencyManagement();
335         dependencyManagement.setDependencies(createArtifacts(getDependencyMgtList(item)));
336         project.getModel().setDependencyManagement(dependencyManagement);
337 
338         mojo.execute();
339         assertMarkerFile(mojo, true, item);
340         assertEquals("3.0-SNAPSHOT", item.getVersion());
341     }
342 
343     @Test
344     @InjectMojo(goal = "unpack")
345     void testMissingVersionFromDependencyMgtWithClassifier(UnpackMojo mojo) throws Exception {
346         ArtifactItem item = new ArtifactItem();
347 
348         item.setArtifactId("artifactId");
349         item.setClassifier("classifier");
350         item.setGroupId("groupId");
351         item.setType("jar");
352 
353         MavenProject project = mojo.getProject();
354         project.setDependencies(createArtifacts(getDependencyList(item)));
355 
356         item = new ArtifactItem();
357 
358         item.setArtifactId("artifactId-2");
359         item.setClassifier("classifier");
360         item.setGroupId("groupId");
361         item.setType("jar");
362 
363         stubFactory.createArtifact(
364                 "groupId",
365                 "artifactId-2",
366                 VersionRange.createFromVersion("3.0-SNAPSHOT"),
367                 null,
368                 "jar",
369                 "classifier",
370                 false);
371         stubFactory.createArtifact(
372                 "groupId", "artifactId-2", VersionRange.createFromVersion("3.1"), null, "jar", "classifier", false);
373 
374         List<ArtifactItem> list = new ArrayList<>();
375         list.add(item);
376 
377         mojo.setArtifactItems(list);
378 
379         DependencyManagement dependencyManagement = new DependencyManagement();
380         dependencyManagement.setDependencies(createArtifacts(getDependencyMgtList(item)));
381         project.getModel().setDependencyManagement(dependencyManagement);
382 
383         mojo.execute();
384 
385         assertMarkerFile(mojo, true, item);
386         assertEquals("3.1", item.getVersion());
387     }
388 
389     @Test
390     @InjectMojo(goal = "unpack")
391     void testArtifactNotFound(UnpackMojo mojo) throws Exception {
392         ArtifactItem item = new ArtifactItem();
393 
394         item.setArtifactId("artifactId");
395         item.setClassifier("");
396         item.setGroupId("groupId");
397         item.setType("type");
398         item.setVersion("1.0");
399 
400         List<ArtifactItem> list = new ArrayList<>();
401         list.add(item);
402         mojo.setArtifactItems(list);
403 
404         try {
405             mojo.execute();
406             fail("ExpectedException");
407         } catch (MojoExecutionException e) {
408             assertEquals("Unable to find/resolve artifact.", e.getMessage());
409         }
410     }
411 
412     @Test
413     @InjectMojo(goal = "unpack")
414     void testNoArtifactItems(UnpackMojo mojo) {
415         try {
416             mojo.getProcessedArtifactItems(false);
417             fail("Expected Exception");
418         } catch (MojoExecutionException e) {
419             assertEquals("There are no artifactItems configured.", e.getMessage());
420         }
421     }
422 
423     @Test
424     @InjectMojo(goal = "unpack")
425     void testUnpackDontOverWriteReleases(UnpackMojo mojo) throws Exception {
426         stubFactory.setCreateFiles(true);
427         Artifact release = stubFactory.getReleaseArtifact();
428         assertTrue(release.getFile().setLastModified(System.currentTimeMillis() - 2000));
429 
430         ArtifactItem item = new ArtifactItem(createArtifact(release));
431 
432         List<ArtifactItem> list = new ArrayList<>(1);
433         list.add(item);
434         mojo.setArtifactItems(list);
435 
436         mojo.setOverWriteIfNewer(false);
437 
438         mojo.execute();
439 
440         assertUnpacked(mojo, item, false);
441     }
442 
443     @Test
444     @InjectMojo(goal = "unpack")
445     void testUnpackDontOverWriteSnapshots(UnpackMojo mojo) throws Exception {
446         stubFactory.setCreateFiles(true);
447         Artifact artifact = stubFactory.getSnapshotArtifact();
448         assertTrue(artifact.getFile().setLastModified(System.currentTimeMillis() - 2000));
449 
450         ArtifactItem item = new ArtifactItem(createArtifact(artifact));
451 
452         List<ArtifactItem> list = new ArrayList<>(1);
453         list.add(item);
454         mojo.setArtifactItems(list);
455 
456         mojo.setOverWriteIfNewer(false);
457 
458         mojo.execute();
459 
460         assertUnpacked(mojo, item, false);
461     }
462 
463     @Test
464     @InjectMojo(goal = "unpack")
465     void testUnpackOverWriteReleases(UnpackMojo mojo) throws Exception {
466         stubFactory.setCreateFiles(true);
467         Artifact release = stubFactory.getReleaseArtifact();
468         assertTrue(release.getFile().setLastModified(System.currentTimeMillis() - 2000));
469 
470         ArtifactItem item = new ArtifactItem(createArtifact(release));
471 
472         List<ArtifactItem> list = new ArrayList<>(1);
473         list.add(item);
474         mojo.setArtifactItems(list);
475 
476         mojo.setOverWriteIfNewer(false);
477         mojo.setOverWriteReleases(true);
478         mojo.execute();
479 
480         assertUnpacked(mojo, item, true);
481     }
482 
483     @Test
484     @InjectMojo(goal = "unpack")
485     void testUnpackOverWriteSnapshot(UnpackMojo mojo) throws Exception {
486         stubFactory.setCreateFiles(true);
487         Artifact artifact = stubFactory.getSnapshotArtifact();
488         assertTrue(artifact.getFile().setLastModified(System.currentTimeMillis() - 2000));
489 
490         ArtifactItem item = new ArtifactItem(createArtifact(artifact));
491 
492         List<ArtifactItem> list = new ArrayList<>(1);
493         list.add(item);
494         mojo.setArtifactItems(list);
495 
496         mojo.setOverWriteIfNewer(false);
497         mojo.setOverWriteReleases(false);
498         mojo.setOverWriteSnapshots(true);
499         mojo.execute();
500 
501         assertUnpacked(mojo, item, true);
502     }
503 
504     /**
505      * The following code has been modified to prevent the
506      * JDK bug which is described in detail
507      * https://bugs.openjdk.java.net/browse/JDK-8177809
508      *
509      */
510     @Test
511     @InjectMojo(goal = "unpack")
512     void testUnpackOverWriteIfNewer(UnpackMojo mojo) throws Exception {
513         final long now = System.currentTimeMillis();
514 
515         stubFactory.setCreateFiles(true);
516         Artifact artifact = stubFactory.getSnapshotArtifact();
517         assertTrue(artifact.getFile().setLastModified(now - 20000));
518 
519         ArtifactItem item = new ArtifactItem(createArtifact(artifact));
520 
521         List<ArtifactItem> list = Collections.singletonList(item);
522         mojo.setArtifactItems(list);
523         mojo.setOverWriteIfNewer(true);
524         mojo.execute();
525         File unpackedFile = getUnpackedFile(item);
526 
527         // round down to the last second
528         long time = now;
529         time = time - (time % 1000);
530         // go back 30 more seconds for linux
531         time -= 30000;
532         // set to known value
533         assertTrue(unpackedFile.setLastModified(time));
534         // set source to be newer about some seconds,
535         // especially on macOS it shouldn't be smaller than 16s in order to mitigate flapping test
536         assertTrue(artifact.getFile().setLastModified(time + 16000));
537 
538         // manually set markerfile (must match getMarkerFile in DefaultMarkerFileHandler)
539         File marker = new File(mojo.getMarkersDirectory(), artifact.getId().replace(':', '-') + ".marker");
540         assertTrue(marker.setLastModified(time));
541 
542         mojo.execute();
543 
544         FileTime markerLastModifiedMillis = Files.getLastModifiedTime(marker.toPath());
545         FileTime unpackedFileLastModifiedMillis = Files.getLastModifiedTime(unpackedFile.toPath());
546 
547         assertNotEquals(
548                 markerLastModifiedMillis,
549                 unpackedFileLastModifiedMillis,
550                 "unpackedFile '" + unpackedFile + "' lastModified() == " + markerLastModifiedMillis
551                         + ": should be different");
552     }
553 
554     private void assertUnpacked(UnpackMojo mojo, ArtifactItem item, boolean overWrite) throws Exception {
555 
556         File unpackedFile = getUnpackedFile(item);
557 
558         Thread.sleep(100);
559         // round down to the last second
560         long time = System.currentTimeMillis();
561         time = time - (time % 1000);
562         assertTrue(unpackedFile.setLastModified(time));
563 
564         assertEquals(time, unpackedFile.lastModified());
565         mojo.execute();
566 
567         if (overWrite) {
568             assertNotEquals(time, unpackedFile.lastModified());
569         } else {
570             assertEquals(time, unpackedFile.lastModified());
571         }
572     }
573 
574     private File getUnpackedFile(ArtifactItem item) {
575         File unpackedFile = new File(
576                 item.getOutputDirectory(), DependencyArtifactStubFactory.getUnpackableFileName(item.getArtifact()));
577 
578         assertTrue(unpackedFile.exists());
579         return unpackedFile;
580     }
581 
582     // respects the createUnpackableFile flag of the ArtifactStubFactory
583     private List<Dependency> createArtifacts(List<Dependency> items) throws IOException {
584         for (Dependency item : items) {
585             String classifier = "".equals(item.getClassifier()) ? null : item.getClassifier();
586             stubFactory.createArtifact(
587                     item.getGroupId(),
588                     item.getArtifactId(),
589                     VersionRange.createFromVersion(item.getVersion()),
590                     null,
591                     item.getType(),
592                     classifier,
593                     item.isOptional());
594         }
595         return items;
596     }
597 
598     private Artifact createArtifact(Artifact art) throws IOException {
599         String classifier = "".equals(art.getClassifier()) ? null : art.getClassifier();
600         stubFactory.createArtifact(
601                 art.getGroupId(),
602                 art.getArtifactId(),
603                 VersionRange.createFromVersion(art.getVersion()),
604                 null,
605                 art.getType(),
606                 classifier,
607                 art.isOptional());
608         return art;
609     }
610 
611     private ArtifactItem createArtifact(ArtifactItem item) throws IOException {
612         String classifier = "".equals(item.getClassifier()) ? null : item.getClassifier();
613         stubFactory.createArtifact(
614                 item.getGroupId(), item.getArtifactId(), item.getVersion(), null, item.getType(), classifier);
615         return item;
616     }
617 }