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