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