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.Before;
45 import org.junit.Test;
46
47 import static java.util.stream.Collectors.toList;
48 import static org.hamcrest.MatcherAssert.assertThat;
49 import static org.hamcrest.Matchers.containsString;
50 import static org.hamcrest.Matchers.empty;
51 import static org.hamcrest.Matchers.equalTo;
52 import static org.hamcrest.Matchers.not;
53 import static org.hamcrest.Matchers.notNullValue;
54
55
56
57
58 public class TrustedChecksumsArtifactResolverPostProcessorTest implements TrustedChecksumsSource {
59 private static final String TRUSTED_SOURCE_NAME = "test";
60
61 private Artifact artifactWithoutTrustedChecksum;
62
63 private Artifact artifactWithTrustedChecksum;
64
65 private String artifactTrustedChecksum;
66
67 protected DefaultRepositorySystemSession session;
68
69 protected ChecksumAlgorithmFactory checksumAlgorithmFactory = new Sha1ChecksumAlgorithmFactory();
70
71 private TrustedChecksumsArtifactResolverPostProcessor subject;
72
73 private TrustedChecksumsSource.Writer trustedChecksumsWriter;
74
75 @Before
76 public void prepareSubject() throws IOException {
77 Files.createDirectories(Paths.get(System.getProperty("java.io.tmpdir")));
78
79 File tmp = Files.createTempFile("artifact", "tmp").toFile();
80 artifactWithoutTrustedChecksum = new DefaultArtifact("test:test:1.0").setFile(tmp);
81 artifactWithTrustedChecksum = new DefaultArtifact("test:test:2.0").setFile(tmp);
82 artifactTrustedChecksum = "da39a3ee5e6b4b0d3255bfef95601890afd80709";
83
84 session = TestUtils.newSession();
85 ChecksumAlgorithmFactorySelector selector = new ChecksumAlgorithmFactorySelector() {
86 @Override
87 public ChecksumAlgorithmFactory select(String algorithmName) {
88 if (checksumAlgorithmFactory.getName().equals(algorithmName)) {
89 return checksumAlgorithmFactory;
90 }
91 throw new IllegalArgumentException("no alg factory for " + algorithmName);
92 }
93
94 @Override
95 public List<ChecksumAlgorithmFactory> selectList(Collection<String> algorithmNames) {
96 return algorithmNames.stream().map(this::select).collect(toList());
97 }
98
99 @Override
100 public Collection<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories() {
101 return Collections.singletonList(checksumAlgorithmFactory);
102 }
103
104 @Override
105 public boolean isChecksumExtension(String extension) {
106 throw new RuntimeException("not implemented");
107 }
108 };
109 subject = new TrustedChecksumsArtifactResolverPostProcessor(
110 selector, Collections.singletonMap(TRUSTED_SOURCE_NAME, this));
111 trustedChecksumsWriter = null;
112 session.setConfigProperty("aether.artifactResolver.postProcessor.trustedChecksums", Boolean.TRUE.toString());
113 }
114
115
116
117 @Override
118 public Map<String, String> getTrustedArtifactChecksums(
119 RepositorySystemSession session,
120 Artifact artifact,
121 ArtifactRepository artifactRepository,
122 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories) {
123 if (ArtifactIdUtils.toId(artifactWithTrustedChecksum).equals(ArtifactIdUtils.toId(artifact))) {
124 return Collections.singletonMap(checksumAlgorithmFactory.getName(), artifactTrustedChecksum);
125 } else {
126 return Collections.emptyMap();
127 }
128 }
129
130 @Override
131 public Writer getTrustedArtifactChecksumsWriter(RepositorySystemSession session) {
132 return trustedChecksumsWriter;
133 }
134
135
136
137 private ArtifactResult createArtifactResult(Artifact artifact) {
138 ArtifactResult artifactResult = new ArtifactResult(new ArtifactRequest().setArtifact(artifact));
139 artifactResult.setArtifact(artifact);
140 return artifactResult;
141 }
142
143
144
145 @Test
146 public void haveMatchingChecksumPass() {
147 ArtifactResult artifactResult = createArtifactResult(artifactWithTrustedChecksum);
148 assertThat(artifactResult.isResolved(), equalTo(true));
149
150 subject.postProcess(session, Collections.singletonList(artifactResult));
151 assertThat(artifactResult.isResolved(), equalTo(true));
152 }
153
154 @Test
155 public void haveNoChecksumPass() {
156 ArtifactResult artifactResult = createArtifactResult(artifactWithoutTrustedChecksum);
157 assertThat(artifactResult.isResolved(), equalTo(true));
158
159 subject.postProcess(session, Collections.singletonList(artifactResult));
160 assertThat(artifactResult.isResolved(), equalTo(true));
161 }
162
163 @Test
164 public void haveNoChecksumFailIfMissingEnabledFail() {
165 session.setConfigProperty(
166 "aether.artifactResolver.postProcessor.trustedChecksums.failIfMissing", Boolean.TRUE.toString());
167 ArtifactResult artifactResult = createArtifactResult(artifactWithoutTrustedChecksum);
168 assertThat(artifactResult.isResolved(), equalTo(true));
169
170 subject.postProcess(session, Collections.singletonList(artifactResult));
171 assertThat(artifactResult.isResolved(), equalTo(false));
172 assertThat(artifactResult.getExceptions(), not(empty()));
173 assertThat(
174 artifactResult.getExceptions().get(0).getMessage(),
175 containsString("Missing from " + TRUSTED_SOURCE_NAME + " trusted"));
176 }
177
178 @Test
179 public void haveMismatchingChecksumFail() {
180 artifactTrustedChecksum = "foobar";
181 ArtifactResult artifactResult = createArtifactResult(artifactWithTrustedChecksum);
182 assertThat(artifactResult.isResolved(), equalTo(true));
183
184 subject.postProcess(session, Collections.singletonList(artifactResult));
185 assertThat(artifactResult.isResolved(), equalTo(false));
186 assertThat(artifactResult.getExceptions(), not(empty()));
187 assertThat(artifactResult.getExceptions().get(0).getMessage(), containsString("trusted checksum mismatch"));
188 assertThat(
189 artifactResult.getExceptions().get(0).getMessage(),
190 containsString(TRUSTED_SOURCE_NAME + "=" + artifactTrustedChecksum));
191 }
192
193 @Test
194 public void recordCalculatedChecksum() {
195 AtomicReference<String> recordedChecksum = new AtomicReference<>(null);
196 this.trustedChecksumsWriter = new Writer() {
197 @Override
198 public void addTrustedArtifactChecksums(
199 Artifact artifact,
200 ArtifactRepository artifactRepository,
201 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories,
202 Map<String, String> trustedArtifactChecksums) {
203 recordedChecksum.set(trustedArtifactChecksums.get(checksumAlgorithmFactory.getName()));
204 }
205 };
206 session.setConfigProperty(
207 "aether.artifactResolver.postProcessor.trustedChecksums.record", Boolean.TRUE.toString());
208 ArtifactResult artifactResult = createArtifactResult(artifactWithTrustedChecksum);
209 assertThat(artifactResult.isResolved(), equalTo(true));
210
211 subject.postProcess(session, Collections.singletonList(artifactResult));
212 assertThat(artifactResult.isResolved(), equalTo(true));
213
214 String checksum = recordedChecksum.get();
215 assertThat(checksum, notNullValue());
216 assertThat(checksum, equalTo(artifactTrustedChecksum));
217 }
218 }