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;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.net.URI;
26 import java.net.URISyntaxException;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.List;
31 import java.util.Set;
32 import java.util.stream.Collectors;
33
34 import org.eclipse.aether.ConfigurationProperties;
35 import org.eclipse.aether.RepositorySystemSession;
36 import org.eclipse.aether.artifact.Artifact;
37 import org.eclipse.aether.metadata.Metadata;
38 import org.eclipse.aether.repository.RemoteRepository;
39 import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
40 import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;
41 import org.eclipse.aether.spi.connector.layout.RepositoryLayout;
42 import org.eclipse.aether.spi.connector.layout.RepositoryLayoutFactory;
43 import org.eclipse.aether.transfer.NoRepositoryLayoutException;
44 import org.eclipse.aether.util.ConfigUtils;
45
46 import static java.util.Objects.requireNonNull;
47
48
49
50
51 @Singleton
52 @Named(Maven2RepositoryLayoutFactory.NAME)
53 public final class Maven2RepositoryLayoutFactory implements RepositoryLayoutFactory {
54 public static final String NAME = "maven2";
55
56 private static final String CONFIG_PROPS_PREFIX = ConfigurationProperties.PREFIX_LAYOUT + NAME + ".";
57
58
59
60
61
62
63
64
65
66
67
68 public static final String CONFIG_PROP_CHECKSUMS_ALGORITHMS = CONFIG_PROPS_PREFIX + "checksumAlgorithms";
69
70 public static final String DEFAULT_CHECKSUMS_ALGORITHMS = "SHA-1,MD5";
71
72
73
74
75
76
77
78
79
80
81
82 public static final String CONFIG_PROP_OMIT_CHECKSUMS_FOR_EXTENSIONS =
83 CONFIG_PROPS_PREFIX + "omitChecksumsForExtensions";
84
85 public static final String DEFAULT_OMIT_CHECKSUMS_FOR_EXTENSIONS = ".asc,.sigstore";
86
87 private float priority;
88
89 private final ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector;
90
91 public float getPriority() {
92 return priority;
93 }
94
95 @Inject
96 public Maven2RepositoryLayoutFactory(ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector) {
97 this.checksumAlgorithmFactorySelector = requireNonNull(checksumAlgorithmFactorySelector);
98 }
99
100
101
102
103
104
105
106 public Maven2RepositoryLayoutFactory setPriority(float priority) {
107 this.priority = priority;
108 return this;
109 }
110
111 public RepositoryLayout newInstance(RepositorySystemSession session, RemoteRepository repository)
112 throws NoRepositoryLayoutException {
113 requireNonNull(session, "session cannot be null");
114 requireNonNull(repository, "repository cannot be null");
115 if (!"default".equals(repository.getContentType())) {
116 throw new NoRepositoryLayoutException(repository);
117 }
118
119 List<ChecksumAlgorithmFactory> checksumsAlgorithms = checksumAlgorithmFactorySelector.selectList(
120 ConfigUtils.parseCommaSeparatedUniqueNames(ConfigUtils.getString(
121 session,
122 DEFAULT_CHECKSUMS_ALGORITHMS,
123 CONFIG_PROP_CHECKSUMS_ALGORITHMS + "." + repository.getId(),
124 CONFIG_PROP_CHECKSUMS_ALGORITHMS)));
125
126
127 Set<String> omitChecksumsForExtensions = Arrays.stream(ConfigUtils.getString(
128 session,
129 DEFAULT_OMIT_CHECKSUMS_FOR_EXTENSIONS,
130 CONFIG_PROP_OMIT_CHECKSUMS_FOR_EXTENSIONS)
131 .split(","))
132 .filter(s -> s != null && !s.trim().isEmpty())
133 .collect(Collectors.toSet());
134
135
136 if (omitChecksumsForExtensions.stream().anyMatch(s -> !s.startsWith("."))) {
137 throw new IllegalArgumentException(String.format(
138 "The configuration %s contains illegal values: %s (all entries must start with '.' (dot))",
139 CONFIG_PROP_OMIT_CHECKSUMS_FOR_EXTENSIONS, omitChecksumsForExtensions));
140 }
141
142 return new Maven2RepositoryLayout(
143 checksumAlgorithmFactorySelector, checksumsAlgorithms, omitChecksumsForExtensions);
144 }
145
146 private static class Maven2RepositoryLayout implements RepositoryLayout {
147 private final ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector;
148
149 private final List<ChecksumAlgorithmFactory> configuredChecksumAlgorithms;
150
151 private final Set<String> extensionsWithoutChecksums;
152
153 private Maven2RepositoryLayout(
154 ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector,
155 List<ChecksumAlgorithmFactory> configuredChecksumAlgorithms,
156 Set<String> extensionsWithoutChecksums) {
157 this.checksumAlgorithmFactorySelector = requireNonNull(checksumAlgorithmFactorySelector);
158 this.configuredChecksumAlgorithms = Collections.unmodifiableList(configuredChecksumAlgorithms);
159 this.extensionsWithoutChecksums = requireNonNull(extensionsWithoutChecksums);
160 }
161
162 private URI toUri(String path) {
163 try {
164 return new URI(null, null, path, null);
165 } catch (URISyntaxException e) {
166 throw new IllegalStateException(e);
167 }
168 }
169
170 @Override
171 public List<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories() {
172 return configuredChecksumAlgorithms;
173 }
174
175 @Override
176 public boolean hasChecksums(Artifact artifact) {
177 String artifactExtension = artifact.getExtension();
178 for (String extensionWithoutChecksums : extensionsWithoutChecksums) {
179 if (artifactExtension.endsWith(extensionWithoutChecksums)) {
180 return false;
181 }
182 }
183 return true;
184 }
185
186 @Override
187 public URI getLocation(Artifact artifact, boolean upload) {
188 StringBuilder path = new StringBuilder(128);
189
190 path.append(artifact.getGroupId().replace('.', '/')).append('/');
191
192 path.append(artifact.getArtifactId()).append('/');
193
194 path.append(artifact.getBaseVersion()).append('/');
195
196 path.append(artifact.getArtifactId()).append('-').append(artifact.getVersion());
197
198 if (!artifact.getClassifier().isEmpty()) {
199 path.append('-').append(artifact.getClassifier());
200 }
201
202 if (!artifact.getExtension().isEmpty()) {
203 path.append('.').append(artifact.getExtension());
204 }
205
206 return toUri(path.toString());
207 }
208
209 @Override
210 public URI getLocation(Metadata metadata, boolean upload) {
211 StringBuilder path = new StringBuilder(128);
212
213 if (!metadata.getGroupId().isEmpty()) {
214 path.append(metadata.getGroupId().replace('.', '/')).append('/');
215
216 if (!metadata.getArtifactId().isEmpty()) {
217 path.append(metadata.getArtifactId()).append('/');
218
219 if (!metadata.getVersion().isEmpty()) {
220 path.append(metadata.getVersion()).append('/');
221 }
222 }
223 }
224
225 path.append(metadata.getType());
226
227 return toUri(path.toString());
228 }
229
230 @Override
231 public List<ChecksumLocation> getChecksumLocations(Artifact artifact, boolean upload, URI location) {
232 if (!hasChecksums(artifact) || isChecksum(artifact.getExtension())) {
233 return Collections.emptyList();
234 }
235 return getChecksumLocations(location);
236 }
237
238 @Override
239 public List<ChecksumLocation> getChecksumLocations(Metadata metadata, boolean upload, URI location) {
240 return getChecksumLocations(location);
241 }
242
243 private List<ChecksumLocation> getChecksumLocations(URI location) {
244 List<ChecksumLocation> checksumLocations = new ArrayList<>(configuredChecksumAlgorithms.size());
245 for (ChecksumAlgorithmFactory checksumAlgorithmFactory : configuredChecksumAlgorithms) {
246 checksumLocations.add(ChecksumLocation.forLocation(location, checksumAlgorithmFactory));
247 }
248 return checksumLocations;
249 }
250
251 private boolean isChecksum(String extension) {
252 return checksumAlgorithmFactorySelector.isChecksumExtension(extension);
253 }
254 }
255 }