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