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.repository.ArtifactRepository;
38 import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
39 import org.eclipse.aether.spi.io.ChecksumProcessor;
40 import org.eclipse.aether.util.ConfigUtils;
41 import org.eclipse.aether.util.repository.RepositoryIdHelper;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
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 @Singleton
65 @Named(SparseDirectoryTrustedChecksumsSource.NAME)
66 public final class SparseDirectoryTrustedChecksumsSource extends FileTrustedChecksumsSourceSupport {
67 public static final String NAME = "sparseDirectory";
68
69 private static final String CONFIG_PROPS_PREFIX =
70 FileTrustedChecksumsSourceSupport.CONFIG_PROPS_PREFIX + NAME + ".";
71
72
73
74
75
76
77
78
79 public static final String CONFIG_PROP_ENABLED = FileTrustedChecksumsSourceSupport.CONFIG_PROPS_PREFIX + NAME;
80
81
82
83
84
85
86
87
88 public static final String CONFIG_PROP_BASEDIR = CONFIG_PROPS_PREFIX + "basedir";
89
90 public static final String LOCAL_REPO_PREFIX_DIR = ".checksums";
91
92
93
94
95
96
97
98
99 public static final String CONFIG_PROP_ORIGIN_AWARE = CONFIG_PROPS_PREFIX + "originAware";
100
101 private static final Logger LOGGER = LoggerFactory.getLogger(SparseDirectoryTrustedChecksumsSource.class);
102
103 private final ChecksumProcessor checksumProcessor;
104
105 private final LocalPathComposer localPathComposer;
106
107 @Inject
108 public SparseDirectoryTrustedChecksumsSource(
109 ChecksumProcessor checksumProcessor, LocalPathComposer localPathComposer) {
110 this.checksumProcessor = requireNonNull(checksumProcessor);
111 this.localPathComposer = requireNonNull(localPathComposer);
112 }
113
114 @Override
115 protected boolean isEnabled(RepositorySystemSession session) {
116 return ConfigUtils.getBoolean(session, false, CONFIG_PROP_ENABLED);
117 }
118
119 private boolean isOriginAware(RepositorySystemSession session) {
120 return ConfigUtils.getBoolean(session, true, CONFIG_PROP_ORIGIN_AWARE);
121 }
122
123 @Override
124 protected Map<String, String> doGetTrustedArtifactChecksums(
125 RepositorySystemSession session,
126 Artifact artifact,
127 ArtifactRepository artifactRepository,
128 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories) {
129 final boolean originAware = isOriginAware(session);
130 final HashMap<String, String> checksums = new HashMap<>();
131 Path basedir = getBasedir(session, LOCAL_REPO_PREFIX_DIR, CONFIG_PROP_BASEDIR, false);
132 if (Files.isDirectory(basedir)) {
133 for (ChecksumAlgorithmFactory checksumAlgorithmFactory : checksumAlgorithmFactories) {
134 Path checksumPath = basedir.resolve(calculateArtifactPath(
135 originAware,
136 artifact,
137 RepositoryIdHelper.cachedIdToPathSegment(session).apply(artifactRepository),
138 checksumAlgorithmFactory));
139
140 if (!Files.isRegularFile(checksumPath)) {
141 LOGGER.debug(
142 "Artifact '{}' trusted checksum '{}' not found on path '{}'",
143 artifact,
144 checksumAlgorithmFactory.getName(),
145 checksumPath);
146 continue;
147 }
148
149 try {
150 String checksum = checksumProcessor.readChecksum(checksumPath);
151 if (checksum != null) {
152 checksums.put(checksumAlgorithmFactory.getName(), checksum);
153 }
154 } catch (IOException e) {
155
156 LOGGER.warn(
157 "Could not read artifact '{}' trusted checksum on path '{}'", artifact, checksumPath, e);
158 throw new UncheckedIOException(e);
159 }
160 }
161 }
162 return checksums;
163 }
164
165 @Override
166 protected Writer doGetTrustedArtifactChecksumsWriter(RepositorySystemSession session) {
167 return new SparseDirectoryWriter(
168 getBasedir(session, LOCAL_REPO_PREFIX_DIR, CONFIG_PROP_BASEDIR, true),
169 isOriginAware(session),
170 RepositoryIdHelper.cachedIdToPathSegment(session));
171 }
172
173 private String calculateArtifactPath(
174 boolean originAware,
175 Artifact artifact,
176 String safeRepositoryId,
177 ChecksumAlgorithmFactory checksumAlgorithmFactory) {
178 String path = localPathComposer.getPathForArtifact(artifact, false) + "."
179 + checksumAlgorithmFactory.getFileExtension();
180 if (originAware) {
181 path = safeRepositoryId + "/" + path;
182 }
183 return path;
184 }
185
186 private class SparseDirectoryWriter implements Writer {
187 private final Path basedir;
188
189 private final boolean originAware;
190
191 private final Function<ArtifactRepository, String> idToPathSegmentFunction;
192
193 private SparseDirectoryWriter(
194 Path basedir, boolean originAware, Function<ArtifactRepository, String> idToPathSegmentFunction) {
195 this.basedir = basedir;
196 this.originAware = originAware;
197 this.idToPathSegmentFunction = idToPathSegmentFunction;
198 }
199
200 @Override
201 public void addTrustedArtifactChecksums(
202 Artifact artifact,
203 ArtifactRepository artifactRepository,
204 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories,
205 Map<String, String> trustedArtifactChecksums)
206 throws IOException {
207 for (ChecksumAlgorithmFactory checksumAlgorithmFactory : checksumAlgorithmFactories) {
208 Path checksumPath = basedir.resolve(calculateArtifactPath(
209 originAware,
210 artifact,
211 idToPathSegmentFunction.apply(artifactRepository),
212 checksumAlgorithmFactory));
213 String checksum = requireNonNull(trustedArtifactChecksums.get(checksumAlgorithmFactory.getName()));
214 checksumProcessor.writeChecksum(checksumPath, checksum);
215 }
216 }
217 }
218 }