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.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   * UT for {@link TrustedChecksumsArtifactResolverPostProcessor}.
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"))); // hack for Surefire
78          // make the two artifacts, BOTH as resolved
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"; // empty file
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     // -- TrustedChecksumsSource interface BEGIN
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     // -- TrustedChecksumsSource interface END
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     // UTs below
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 }