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 checksumsAlgorithms,
146 omitChecksumsForExtensions
147 );
148 }
149
150 private static class Maven2RepositoryLayout
151 implements RepositoryLayout
152 {
153
154 private final List<ChecksumAlgorithmFactory> checksumAlgorithms;
155
156 private final Set<String> extensionsWithoutChecksums;
157
158 private Maven2RepositoryLayout( List<ChecksumAlgorithmFactory> checksumAlgorithms,
159 Set<String> extensionsWithoutChecksums )
160 {
161 this.checksumAlgorithms = Collections.unmodifiableList( checksumAlgorithms );
162 this.extensionsWithoutChecksums = requireNonNull( extensionsWithoutChecksums );
163 }
164
165 private URI toUri( String path )
166 {
167 try
168 {
169 return new URI( null, null, path, null );
170 }
171 catch ( URISyntaxException e )
172 {
173 throw new IllegalStateException( e );
174 }
175 }
176
177 @Override
178 public List<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories()
179 {
180 return checksumAlgorithms;
181 }
182
183 @Override
184 public boolean hasChecksums( Artifact artifact )
185 {
186 String artifactExtension = artifact.getExtension();
187 for ( String extensionWithoutChecksums : extensionsWithoutChecksums )
188 {
189 if ( artifactExtension.endsWith( extensionWithoutChecksums ) )
190 {
191 return false;
192 }
193 }
194 return true;
195 }
196
197 @Override
198 public URI getLocation( Artifact artifact, boolean upload )
199 {
200 StringBuilder path = new StringBuilder( 128 );
201
202 path.append( artifact.getGroupId().replace( '.', '/' ) ).append( '/' );
203
204 path.append( artifact.getArtifactId() ).append( '/' );
205
206 path.append( artifact.getBaseVersion() ).append( '/' );
207
208 path.append( artifact.getArtifactId() ).append( '-' ).append( artifact.getVersion() );
209
210 if ( artifact.getClassifier().length() > 0 )
211 {
212 path.append( '-' ).append( artifact.getClassifier() );
213 }
214
215 if ( artifact.getExtension().length() > 0 )
216 {
217 path.append( '.' ).append( artifact.getExtension() );
218 }
219
220 return toUri( path.toString() );
221 }
222
223 @Override
224 public URI getLocation( Metadata metadata, boolean upload )
225 {
226 StringBuilder path = new StringBuilder( 128 );
227
228 if ( metadata.getGroupId().length() > 0 )
229 {
230 path.append( metadata.getGroupId().replace( '.', '/' ) ).append( '/' );
231
232 if ( metadata.getArtifactId().length() > 0 )
233 {
234 path.append( metadata.getArtifactId() ).append( '/' );
235
236 if ( metadata.getVersion().length() > 0 )
237 {
238 path.append( metadata.getVersion() ).append( '/' );
239 }
240 }
241 }
242
243 path.append( metadata.getType() );
244
245 return toUri( path.toString() );
246 }
247
248 @Override
249 public List<ChecksumLocation> getChecksumLocations( Artifact artifact, boolean upload, URI location )
250 {
251 if ( !hasChecksums( artifact ) || isChecksum( artifact.getExtension() ) )
252 {
253 return Collections.emptyList();
254 }
255 return getChecksumLocations( location );
256 }
257
258 @Override
259 public List<ChecksumLocation> getChecksumLocations( Metadata metadata, boolean upload, URI location )
260 {
261 return getChecksumLocations( location );
262 }
263
264 private List<ChecksumLocation> getChecksumLocations( URI location )
265 {
266 List<ChecksumLocation> checksumLocations = new ArrayList<>( checksumAlgorithms.size() );
267 for ( ChecksumAlgorithmFactory checksumAlgorithmFactory : checksumAlgorithms )
268 {
269 checksumLocations.add( ChecksumLocation.forLocation( location, checksumAlgorithmFactory ) );
270 }
271 return checksumLocations;
272 }
273
274 private boolean isChecksum( String extension )
275 {
276 return checksumAlgorithms.stream().anyMatch( a -> extension.endsWith( "." + a.getFileExtension() ) );
277 }
278 }
279 }