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