1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.internal.impl.resolution;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.nio.file.Files;
24 import java.nio.file.Paths;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.concurrent.atomic.AtomicReference;
30
31 import org.eclipse.aether.DefaultRepositorySystemSession;
32 import org.eclipse.aether.RepositorySystemSession;
33 import org.eclipse.aether.artifact.Artifact;
34 import org.eclipse.aether.artifact.DefaultArtifact;
35 import org.eclipse.aether.internal.impl.checksum.Sha1ChecksumAlgorithmFactory;
36 import org.eclipse.aether.internal.test.util.TestUtils;
37 import org.eclipse.aether.repository.ArtifactRepository;
38 import org.eclipse.aether.resolution.ArtifactRequest;
39 import org.eclipse.aether.resolution.ArtifactResult;
40 import org.eclipse.aether.spi.checksums.TrustedChecksumsSource;
41 import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
42 import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;
43 import org.eclipse.aether.util.artifact.ArtifactIdUtils;
44 import org.junit.jupiter.api.BeforeEach;
45 import org.junit.jupiter.api.Test;
46
47 import static java.util.stream.Collectors.toList;
48 import static org.junit.jupiter.api.Assertions.*;
49
50
51
52
53 public class TrustedChecksumsArtifactResolverPostProcessorTest implements TrustedChecksumsSource {
54 private static final String TRUSTED_SOURCE_NAME = "test";
55
56 private Artifact artifactWithoutTrustedChecksum;
57
58 private Artifact artifactWithTrustedChecksum;
59
60 private String artifactTrustedChecksum;
61
62 protected DefaultRepositorySystemSession session;
63
64 protected ChecksumAlgorithmFactory checksumAlgorithmFactory = new Sha1ChecksumAlgorithmFactory();
65
66 private TrustedChecksumsArtifactResolverPostProcessor subject;
67
68 private TrustedChecksumsSource.Writer trustedChecksumsWriter;
69
70 @BeforeEach
71 void prepareSubject() throws IOException {
72 Files.createDirectories(Paths.get(System.getProperty("java.io.tmpdir")));
73
74 File tmp = Files.createTempFile("artifact", "tmp").toFile();
75 artifactWithoutTrustedChecksum = new DefaultArtifact("test:test:1.0").setFile(tmp);
76 artifactWithTrustedChecksum = new DefaultArtifact("test:test:2.0").setFile(tmp);
77 artifactTrustedChecksum = "da39a3ee5e6b4b0d3255bfef95601890afd80709";
78
79 session = TestUtils.newSession();
80 ChecksumAlgorithmFactorySelector selector = new ChecksumAlgorithmFactorySelector() {
81 @Override
82 public ChecksumAlgorithmFactory select(String algorithmName) {
83 if (checksumAlgorithmFactory.getName().equals(algorithmName)) {
84 return checksumAlgorithmFactory;
85 }
86 throw new IllegalArgumentException("no alg factory for " + algorithmName);
87 }
88
89 @Override
90 public List<ChecksumAlgorithmFactory> selectList(Collection<String> algorithmNames) {
91 return algorithmNames.stream().map(this::select).collect(toList());
92 }
93
94 @Override
95 public Collection<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories() {
96 return Collections.singletonList(checksumAlgorithmFactory);
97 }
98
99 @Override
100 public boolean isChecksumExtension(String extension) {
101 throw new RuntimeException("not implemented");
102 }
103 };
104 subject = new TrustedChecksumsArtifactResolverPostProcessor(
105 selector, Collections.singletonMap(TRUSTED_SOURCE_NAME, this));
106 trustedChecksumsWriter = null;
107 session.setConfigProperty("aether.artifactResolver.postProcessor.trustedChecksums", Boolean.TRUE.toString());
108 }
109
110
111
112 @Override
113 public Map<String, String> getTrustedArtifactChecksums(
114 RepositorySystemSession session,
115 Artifact artifact,
116 ArtifactRepository artifactRepository,
117 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories) {
118 if (ArtifactIdUtils.toId(artifactWithTrustedChecksum).equals(ArtifactIdUtils.toId(artifact))) {
119 return Collections.singletonMap(checksumAlgorithmFactory.getName(), artifactTrustedChecksum);
120 } else {
121 return Collections.emptyMap();
122 }
123 }
124
125 @Override
126 public Writer getTrustedArtifactChecksumsWriter(RepositorySystemSession session) {
127 return trustedChecksumsWriter;
128 }
129
130
131
132 private ArtifactResult createArtifactResult(Artifact artifact) {
133 ArtifactResult artifactResult = new ArtifactResult(new ArtifactRequest().setArtifact(artifact));
134 artifactResult.setArtifact(artifact);
135 return artifactResult;
136 }
137
138
139
140 @Test
141 void haveMatchingChecksumPass() {
142 ArtifactResult artifactResult = createArtifactResult(artifactWithTrustedChecksum);
143 assertTrue(artifactResult.isResolved());
144
145 subject.postProcess(session, Collections.singletonList(artifactResult));
146 assertTrue(artifactResult.isResolved());
147 }
148
149 @Test
150 void haveNoChecksumPass() {
151 ArtifactResult artifactResult = createArtifactResult(artifactWithoutTrustedChecksum);
152 assertTrue(artifactResult.isResolved());
153
154 subject.postProcess(session, Collections.singletonList(artifactResult));
155 assertTrue(artifactResult.isResolved());
156 }
157
158 @Test
159 void haveNoChecksumFailIfMissingEnabledFail() {
160 session.setConfigProperty(
161 "aether.artifactResolver.postProcessor.trustedChecksums.failIfMissing", Boolean.TRUE.toString());
162 ArtifactResult artifactResult = createArtifactResult(artifactWithoutTrustedChecksum);
163 assertTrue(artifactResult.isResolved());
164
165 subject.postProcess(session, Collections.singletonList(artifactResult));
166 assertFalse(artifactResult.isResolved());
167 assertFalse(artifactResult.getExceptions().isEmpty());
168 assertTrue(artifactResult
169 .getExceptions()
170 .get(0)
171 .getMessage()
172 .contains("Missing from " + TRUSTED_SOURCE_NAME + " trusted"));
173 }
174
175 @Test
176 void haveMismatchingChecksumFail() {
177 artifactTrustedChecksum = "foobar";
178 ArtifactResult artifactResult = createArtifactResult(artifactWithTrustedChecksum);
179 assertTrue(artifactResult.isResolved());
180
181 subject.postProcess(session, Collections.singletonList(artifactResult));
182 assertFalse(artifactResult.isResolved());
183 assertFalse(artifactResult.getExceptions().isEmpty());
184 assertTrue(artifactResult.getExceptions().get(0).getMessage().contains("trusted checksum mismatch"));
185 assertTrue(artifactResult
186 .getExceptions()
187 .get(0)
188 .getMessage()
189 .contains(TRUSTED_SOURCE_NAME + "=" + artifactTrustedChecksum));
190 }
191
192 @Test
193 void recordCalculatedChecksum() {
194 AtomicReference<String> recordedChecksum = new AtomicReference<>(null);
195 this.trustedChecksumsWriter = new Writer() {
196 @Override
197 public void addTrustedArtifactChecksums(
198 Artifact artifact,
199 ArtifactRepository artifactRepository,
200 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories,
201 Map<String, String> trustedArtifactChecksums) {
202 recordedChecksum.set(trustedArtifactChecksums.get(checksumAlgorithmFactory.getName()));
203 }
204 };
205 session.setConfigProperty(
206 "aether.artifactResolver.postProcessor.trustedChecksums.record", Boolean.TRUE.toString());
207 ArtifactResult artifactResult = createArtifactResult(artifactWithTrustedChecksum);
208 assertTrue(artifactResult.isResolved());
209
210 subject.postProcess(session, Collections.singletonList(artifactResult));
211 assertTrue(artifactResult.isResolved());
212
213 String checksum = recordedChecksum.get();
214 assertNotNull(checksum);
215 assertEquals(checksum, artifactTrustedChecksum);
216 }
217 }