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.checksum;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.io.IOException;
26 import java.io.UncheckedIOException;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.function.Function;
33
34 import org.eclipse.aether.RepositorySystemSession;
35 import org.eclipse.aether.artifact.Artifact;
36 import org.eclipse.aether.internal.impl.LocalPathComposer;
37 import org.eclipse.aether.metadata.Metadata;
38 import org.eclipse.aether.repository.ArtifactRepository;
39 import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
40 import org.eclipse.aether.spi.io.ChecksumProcessor;
41 import org.eclipse.aether.spi.remoterepo.RepositoryKeyFunctionFactory;
42 import org.eclipse.aether.util.ConfigUtils;
43 import org.eclipse.aether.util.PathUtils;
44
45 import static java.util.Objects.requireNonNull;
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 @Singleton
67 @Named(SparseDirectoryTrustedChecksumsSource.NAME)
68 public final class SparseDirectoryTrustedChecksumsSource extends FileTrustedChecksumsSourceSupport {
69 public static final String NAME = "sparseDirectory";
70
71 private static final String CONFIG_PROPS_PREFIX =
72 FileTrustedChecksumsSourceSupport.CONFIG_PROPS_PREFIX + NAME + ".";
73
74
75
76
77
78
79
80
81 public static final String CONFIG_PROP_ENABLED = FileTrustedChecksumsSourceSupport.CONFIG_PROPS_PREFIX + NAME;
82
83
84
85
86
87
88
89
90 public static final String CONFIG_PROP_BASEDIR = CONFIG_PROPS_PREFIX + "basedir";
91
92 public static final String LOCAL_REPO_PREFIX_DIR = ".checksums";
93
94
95
96
97
98
99
100
101 public static final String CONFIG_PROP_ORIGIN_AWARE = CONFIG_PROPS_PREFIX + "originAware";
102
103 private final ChecksumProcessor checksumProcessor;
104
105 private final LocalPathComposer localPathComposer;
106
107 @Inject
108 public SparseDirectoryTrustedChecksumsSource(
109 RepositoryKeyFunctionFactory repositoryKeyFunctionFactory,
110 ChecksumProcessor checksumProcessor,
111 LocalPathComposer localPathComposer) {
112 super(repositoryKeyFunctionFactory);
113 this.checksumProcessor = requireNonNull(checksumProcessor);
114 this.localPathComposer = requireNonNull(localPathComposer);
115 }
116
117 @Override
118 protected boolean isEnabled(RepositorySystemSession session) {
119 return ConfigUtils.getBoolean(session, false, CONFIG_PROP_ENABLED);
120 }
121
122 private boolean isOriginAware(RepositorySystemSession session) {
123 return ConfigUtils.getBoolean(session, true, CONFIG_PROP_ORIGIN_AWARE);
124 }
125
126 @Override
127 protected Map<String, String> doGetTrustedArtifactChecksums(
128 RepositorySystemSession session,
129 Artifact artifact,
130 ArtifactRepository artifactRepository,
131 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories) {
132 final boolean originAware = isOriginAware(session);
133 final HashMap<String, String> checksums = new HashMap<>();
134 Path basedir = getBasedir(session, LOCAL_REPO_PREFIX_DIR, CONFIG_PROP_BASEDIR, false);
135 if (Files.isDirectory(basedir)) {
136 for (ChecksumAlgorithmFactory checksumAlgorithmFactory : checksumAlgorithmFactories) {
137 Path checksumFilePath = null;
138 for (String repoKey : repositoryKey(session, artifactRepository)) {
139 Path checksumPath = basedir.resolve(
140 calculateArtifactPath(originAware, artifact, repoKey, checksumAlgorithmFactory));
141
142 if (Files.isRegularFile(checksumPath)) {
143 checksumFilePath = checksumPath;
144 break;
145 }
146 }
147
148 if (checksumFilePath != null) {
149 try {
150 String checksum = checksumProcessor.readChecksum(checksumFilePath);
151 if (checksum != null) {
152 checksums.putIfAbsent(checksumAlgorithmFactory.getName(), checksum);
153 }
154 } catch (IOException e) {
155
156 logger.warn(
157 "Could not read artifact '{}' trusted checksum on path '{}'",
158 artifact,
159 checksumFilePath,
160 e);
161 throw new UncheckedIOException(e);
162 }
163 }
164 }
165 }
166 return checksums;
167 }
168
169 @Override
170 protected Map<String, String> doGetTrustedMetadataChecksums(
171 RepositorySystemSession session,
172 Metadata metadata,
173 ArtifactRepository artifactRepository,
174 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories) {
175 final boolean originAware = isOriginAware(session);
176 final HashMap<String, String> checksums = new HashMap<>();
177 Path basedir = getBasedir(session, LOCAL_REPO_PREFIX_DIR, CONFIG_PROP_BASEDIR, false);
178 if (Files.isDirectory(basedir)) {
179 for (ChecksumAlgorithmFactory checksumAlgorithmFactory : checksumAlgorithmFactories) {
180 Path checksumFilePath = null;
181 for (String repoKey : repositoryKey(session, artifactRepository)) {
182 Path checksumPath = basedir.resolve(
183 calculateMetadataPath(originAware, metadata, repoKey, checksumAlgorithmFactory));
184
185 if (Files.isRegularFile(checksumPath)) {
186 checksumFilePath = checksumPath;
187 break;
188 }
189 }
190
191 if (checksumFilePath != null) {
192 try {
193 String checksum = checksumProcessor.readChecksum(checksumFilePath);
194 if (checksum != null) {
195 checksums.putIfAbsent(checksumAlgorithmFactory.getName(), checksum);
196 }
197 } catch (IOException e) {
198
199 logger.warn(
200 "Could not read metadata '{}' trusted checksum on path '{}'",
201 metadata,
202 checksumFilePath,
203 e);
204 throw new UncheckedIOException(e);
205 }
206 }
207 }
208 }
209 return checksums;
210 }
211
212 @Override
213 protected Writer doGetTrustedArtifactChecksumsWriter(RepositorySystemSession session) {
214 return new SparseDirectoryWriter(
215 getBasedir(session, LOCAL_REPO_PREFIX_DIR, CONFIG_PROP_BASEDIR, true),
216 isOriginAware(session),
217 r -> repositoryKey(session, r).get(0));
218 }
219
220 private String calculateArtifactPath(
221 boolean originAware,
222 Artifact artifact,
223 String safeRepositoryId,
224 ChecksumAlgorithmFactory checksumAlgorithmFactory) {
225 String path = localPathComposer.getPathForArtifact(artifact, false) + "."
226 + checksumAlgorithmFactory.getFileExtension();
227 if (originAware) {
228
229
230 PathUtils.validatePathComponent(safeRepositoryId, "repository key");
231 path = safeRepositoryId + "/" + path;
232 }
233 return path;
234 }
235
236 private String calculateMetadataPath(
237 boolean originAware,
238 Metadata metadata,
239 String safeRepositoryId,
240 ChecksumAlgorithmFactory checksumAlgorithmFactory) {
241 String path = localPathComposer.getPathForMetadata(metadata, safeRepositoryId) + "."
242 + checksumAlgorithmFactory.getFileExtension();
243 if (originAware) {
244
245 PathUtils.validatePathComponent(safeRepositoryId, "repository key");
246 path = safeRepositoryId + "/" + path;
247 }
248 return path;
249 }
250
251 private class SparseDirectoryWriter implements Writer {
252 private final Path basedir;
253
254 private final boolean originAware;
255
256 private final Function<ArtifactRepository, String> idToPathSegmentFunction;
257
258 private SparseDirectoryWriter(
259 Path basedir, boolean originAware, Function<ArtifactRepository, String> idToPathSegmentFunction) {
260 this.basedir = basedir;
261 this.originAware = originAware;
262 this.idToPathSegmentFunction = idToPathSegmentFunction;
263 }
264
265 @Override
266 public void addTrustedArtifactChecksums(
267 Artifact artifact,
268 ArtifactRepository artifactRepository,
269 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories,
270 Map<String, String> trustedArtifactChecksums)
271 throws IOException {
272 for (ChecksumAlgorithmFactory checksumAlgorithmFactory : checksumAlgorithmFactories) {
273 Path checksumPath = basedir.resolve(calculateArtifactPath(
274 originAware,
275 artifact,
276 idToPathSegmentFunction.apply(artifactRepository),
277 checksumAlgorithmFactory));
278 String checksum = requireNonNull(trustedArtifactChecksums.get(checksumAlgorithmFactory.getName()));
279 checksumProcessor.writeChecksum(checksumPath, checksum);
280 }
281 }
282
283 @Override
284 public void addTrustedMetadataChecksums(
285 Metadata metadata,
286 ArtifactRepository artifactRepository,
287 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories,
288 Map<String, String> trustedMetadataChecksums)
289 throws IOException {
290 for (ChecksumAlgorithmFactory checksumAlgorithmFactory : checksumAlgorithmFactories) {
291 Path checksumPath = basedir.resolve(calculateMetadataPath(
292 originAware,
293 metadata,
294 idToPathSegmentFunction.apply(artifactRepository),
295 checksumAlgorithmFactory));
296 String checksum = requireNonNull(trustedMetadataChecksums.get(checksumAlgorithmFactory.getName()));
297 checksumProcessor.writeChecksum(checksumPath, checksum);
298 }
299 }
300 }
301 }