1 package org.apache.maven.internal.aether;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.LinkedHashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.stream.Collectors;
32
33 import javax.inject.Inject;
34 import javax.inject.Named;
35
36 import org.apache.maven.RepositoryUtils;
37 import org.apache.maven.api.xml.Dom;
38 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
39 import org.apache.maven.bridge.MavenRepositorySystem;
40 import org.apache.maven.eventspy.internal.EventSpyDispatcher;
41 import org.apache.maven.execution.MavenExecutionRequest;
42 import org.apache.maven.feature.Features;
43 import org.apache.maven.internal.xml.XmlPlexusConfiguration;
44 import org.apache.maven.internal.xml.Xpp3Dom;
45 import org.apache.maven.model.building.TransformerContext;
46 import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
47 import org.apache.maven.rtinfo.RuntimeInformation;
48 import org.apache.maven.settings.Mirror;
49 import org.apache.maven.settings.Proxy;
50 import org.apache.maven.settings.Server;
51 import org.apache.maven.settings.building.SettingsProblem;
52 import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
53 import org.apache.maven.settings.crypto.SettingsDecrypter;
54 import org.apache.maven.settings.crypto.SettingsDecryptionResult;
55 import org.codehaus.plexus.configuration.PlexusConfiguration;
56 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
57 import org.eclipse.aether.ConfigurationProperties;
58 import org.eclipse.aether.DefaultRepositorySystemSession;
59 import org.eclipse.aether.RepositorySystem;
60 import org.eclipse.aether.SessionData;
61 import org.eclipse.aether.artifact.Artifact;
62 import org.eclipse.aether.repository.LocalRepository;
63 import org.eclipse.aether.repository.NoLocalRepositoryManagerException;
64 import org.eclipse.aether.repository.RepositoryPolicy;
65 import org.eclipse.aether.repository.WorkspaceReader;
66 import org.eclipse.aether.resolution.ResolutionErrorPolicy;
67 import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
68 import org.eclipse.aether.transform.FileTransformer;
69 import org.eclipse.aether.transform.TransformException;
70 import org.eclipse.aether.util.repository.AuthenticationBuilder;
71 import org.eclipse.aether.util.repository.DefaultAuthenticationSelector;
72 import org.eclipse.aether.util.repository.DefaultMirrorSelector;
73 import org.eclipse.aether.util.repository.DefaultProxySelector;
74 import org.eclipse.aether.util.repository.SimpleResolutionErrorPolicy;
75 import org.eclipse.sisu.Nullable;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
78
79
80
81
82 @Named
83 public class DefaultRepositorySystemSessionFactory
84 {
85 private static final String MAVEN_RESOLVER_TRANSPORT_KEY = "maven.resolver.transport";
86
87 private static final String MAVEN_RESOLVER_TRANSPORT_DEFAULT = "default";
88
89 private static final String MAVEN_RESOLVER_TRANSPORT_WAGON = "wagon";
90
91 private static final String MAVEN_RESOLVER_TRANSPORT_NATIVE = "native";
92
93 private static final String MAVEN_RESOLVER_TRANSPORT_AUTO = "auto";
94
95 private static final String WAGON_TRANSPORTER_PRIORITY_KEY = "aether.priority.WagonTransporterFactory";
96
97 private static final String NATIVE_HTTP_TRANSPORTER_PRIORITY_KEY = "aether.priority.HttpTransporterFactory";
98
99 private static final String NATIVE_FILE_TRANSPORTER_PRIORITY_KEY = "aether.priority.FileTransporterFactory";
100
101 private static final String RESOLVER_MAX_PRIORITY = String.valueOf( Float.MAX_VALUE );
102
103 private final Logger logger = LoggerFactory.getLogger( getClass() );
104
105 private final ArtifactHandlerManager artifactHandlerManager;
106
107 private final RepositorySystem repoSystem;
108
109 private final LocalRepositoryManagerFactory simpleLocalRepoMgrFactory;
110
111 private final WorkspaceReader workspaceRepository;
112
113 private final SettingsDecrypter settingsDecrypter;
114
115 private final EventSpyDispatcher eventSpyDispatcher;
116
117 private final MavenRepositorySystem mavenRepositorySystem;
118
119 private final RuntimeInformation runtimeInformation;
120
121 @SuppressWarnings( "checkstyle:ParameterNumber" )
122 @Inject
123 public DefaultRepositorySystemSessionFactory(
124 ArtifactHandlerManager artifactHandlerManager,
125 RepositorySystem repoSystem,
126 @Nullable @Named( "simple" ) LocalRepositoryManagerFactory simpleLocalRepoMgrFactory,
127 @Nullable @Named( "ide" ) WorkspaceReader workspaceRepository,
128 SettingsDecrypter settingsDecrypter,
129 EventSpyDispatcher eventSpyDispatcher,
130 MavenRepositorySystem mavenRepositorySystem,
131 RuntimeInformation runtimeInformation )
132 {
133 this.artifactHandlerManager = artifactHandlerManager;
134 this.repoSystem = repoSystem;
135 this.simpleLocalRepoMgrFactory = simpleLocalRepoMgrFactory;
136 this.workspaceRepository = workspaceRepository;
137 this.settingsDecrypter = settingsDecrypter;
138 this.eventSpyDispatcher = eventSpyDispatcher;
139 this.mavenRepositorySystem = mavenRepositorySystem;
140 this.runtimeInformation = runtimeInformation;
141 }
142
143 @SuppressWarnings( "checkstyle:methodLength" )
144 public DefaultRepositorySystemSession newRepositorySession( MavenExecutionRequest request )
145 {
146 DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
147 session.setCache( request.getRepositoryCache() );
148
149 Map<Object, Object> configProps = new LinkedHashMap<>();
150 configProps.put( ConfigurationProperties.USER_AGENT, getUserAgent() );
151 configProps.put( ConfigurationProperties.INTERACTIVE, request.isInteractiveMode() );
152 configProps.put( "maven.startTime", request.getStartTime() );
153 configProps.putAll( request.getSystemProperties() );
154 configProps.putAll( request.getUserProperties() );
155
156 session.setOffline( request.isOffline() );
157 session.setChecksumPolicy( request.getGlobalChecksumPolicy() );
158 session.setUpdatePolicy( request.isNoSnapshotUpdates()
159 ? RepositoryPolicy.UPDATE_POLICY_NEVER
160 : request.isUpdateSnapshots() ? RepositoryPolicy.UPDATE_POLICY_ALWAYS : null );
161
162 int errorPolicy = 0;
163 errorPolicy |= request.isCacheNotFound() ? ResolutionErrorPolicy.CACHE_NOT_FOUND
164 : ResolutionErrorPolicy.CACHE_DISABLED;
165 errorPolicy |= request.isCacheTransferError() ? ResolutionErrorPolicy.CACHE_TRANSFER_ERROR
166 : ResolutionErrorPolicy.CACHE_DISABLED;
167 session.setResolutionErrorPolicy(
168 new SimpleResolutionErrorPolicy( errorPolicy, errorPolicy | ResolutionErrorPolicy.CACHE_NOT_FOUND ) );
169
170 session.setArtifactTypeRegistry( RepositoryUtils.newArtifactTypeRegistry( artifactHandlerManager ) );
171
172 LocalRepository localRepo = new LocalRepository( request.getLocalRepository().getBasedir() );
173
174 if ( request.isUseLegacyLocalRepository() )
175 {
176 try
177 {
178 session.setLocalRepositoryManager( simpleLocalRepoMgrFactory.newInstance( session, localRepo ) );
179 logger.info( "Disabling enhanced local repository: using legacy is strongly discouraged to ensure"
180 + " build reproducibility." );
181 }
182 catch ( NoLocalRepositoryManagerException e )
183 {
184 logger.error( "Failed to configure legacy local repository: falling back to default" );
185 session.setLocalRepositoryManager( repoSystem.newLocalRepositoryManager( session, localRepo ) );
186 }
187 }
188 else
189 {
190 session.setLocalRepositoryManager( repoSystem.newLocalRepositoryManager( session, localRepo ) );
191 }
192
193 session.setWorkspaceReader(
194 request.getWorkspaceReader() != null ? request.getWorkspaceReader() : workspaceRepository );
195
196 DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest();
197 decrypt.setProxies( request.getProxies() );
198 decrypt.setServers( request.getServers() );
199 SettingsDecryptionResult decrypted = settingsDecrypter.decrypt( decrypt );
200
201 if ( logger.isDebugEnabled() )
202 {
203 for ( SettingsProblem problem : decrypted.getProblems() )
204 {
205 logger.debug( problem.getMessage(), problem.getException() );
206 }
207 }
208
209 DefaultMirrorSelector mirrorSelector = new DefaultMirrorSelector();
210 for ( Mirror mirror : request.getMirrors() )
211 {
212 mirrorSelector.add( mirror.getId(), mirror.getUrl(), mirror.getLayout(), false, mirror.isBlocked(),
213 mirror.getMirrorOf(), mirror.getMirrorOfLayouts() );
214 }
215 session.setMirrorSelector( mirrorSelector );
216
217 DefaultProxySelector proxySelector = new DefaultProxySelector();
218 for ( Proxy proxy : decrypted.getProxies() )
219 {
220 AuthenticationBuilder authBuilder = new AuthenticationBuilder();
221 authBuilder.addUsername( proxy.getUsername() ).addPassword( proxy.getPassword() );
222 proxySelector.add(
223 new org.eclipse.aether.repository.Proxy( proxy.getProtocol(), proxy.getHost(), proxy.getPort(),
224 authBuilder.build() ), proxy.getNonProxyHosts() );
225 }
226 session.setProxySelector( proxySelector );
227
228 DefaultAuthenticationSelector authSelector = new DefaultAuthenticationSelector();
229 for ( Server server : decrypted.getServers() )
230 {
231 AuthenticationBuilder authBuilder = new AuthenticationBuilder();
232 authBuilder.addUsername( server.getUsername() ).addPassword( server.getPassword() );
233 authBuilder.addPrivateKey( server.getPrivateKey(), server.getPassphrase() );
234 authSelector.add( server.getId(), authBuilder.build() );
235
236 if ( server.getConfiguration() != null )
237 {
238 Dom dom = ( ( org.codehaus.plexus.util.xml.Xpp3Dom ) server.getConfiguration() ).getDom();
239 List<Dom> children = dom.getChildren().stream()
240 .filter( c -> !"wagonProvider".equals( c.getName() ) )
241 .collect( Collectors.toList() );
242 dom = new Xpp3Dom( dom.getName(), null, null, children, null );
243 PlexusConfiguration config = XmlPlexusConfiguration.toPlexusConfiguration( dom );
244 configProps.put( "aether.connector.wagon.config." + server.getId(), config );
245 }
246
247 configProps.put( "aether.connector.perms.fileMode." + server.getId(), server.getFilePermissions() );
248 configProps.put( "aether.connector.perms.dirMode." + server.getId(), server.getDirectoryPermissions() );
249 }
250 session.setAuthenticationSelector( authSelector );
251
252 Object transport = configProps.getOrDefault( MAVEN_RESOLVER_TRANSPORT_KEY, MAVEN_RESOLVER_TRANSPORT_DEFAULT );
253 if ( MAVEN_RESOLVER_TRANSPORT_DEFAULT.equals( transport ) )
254 {
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271 configProps.put( WAGON_TRANSPORTER_PRIORITY_KEY, "6" );
272 }
273 else if ( MAVEN_RESOLVER_TRANSPORT_NATIVE.equals( transport ) )
274 {
275
276 configProps.put( NATIVE_FILE_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY );
277 configProps.put( NATIVE_HTTP_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY );
278 }
279 else if ( MAVEN_RESOLVER_TRANSPORT_WAGON.equals( transport ) )
280 {
281
282 configProps.put( WAGON_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY );
283 }
284 else if ( !MAVEN_RESOLVER_TRANSPORT_AUTO.equals( transport ) )
285 {
286 throw new IllegalArgumentException( "Unknown resolver transport '" + transport
287 + "'. Supported transports are: " + MAVEN_RESOLVER_TRANSPORT_WAGON + ", "
288 + MAVEN_RESOLVER_TRANSPORT_NATIVE + ", " + MAVEN_RESOLVER_TRANSPORT_AUTO );
289 }
290
291 session.setTransferListener( request.getTransferListener() );
292
293 session.setRepositoryListener( eventSpyDispatcher.chainListener( new LoggingRepositoryListener( logger ) ) );
294
295 session.setUserProperties( request.getUserProperties() );
296 session.setSystemProperties( request.getSystemProperties() );
297 session.setConfigProperties( configProps );
298
299 mavenRepositorySystem.injectMirror( request.getRemoteRepositories(), request.getMirrors() );
300 mavenRepositorySystem.injectProxy( session, request.getRemoteRepositories() );
301 mavenRepositorySystem.injectAuthentication( session, request.getRemoteRepositories() );
302
303 mavenRepositorySystem.injectMirror( request.getPluginArtifactRepositories(), request.getMirrors() );
304 mavenRepositorySystem.injectProxy( session, request.getPluginArtifactRepositories() );
305 mavenRepositorySystem.injectAuthentication( session, request.getPluginArtifactRepositories() );
306
307 if ( Features.buildConsumer( request.getUserProperties() ).isActive() )
308 {
309 session.setFileTransformerManager( a -> getTransformersForArtifact( a, session.getData() ) );
310 }
311
312 return session;
313 }
314
315 private String getUserAgent()
316 {
317 String version = runtimeInformation.getMavenVersion();
318 version = version.isEmpty() ? version : "/" + version;
319 return "Apache-Maven" + version + " (Java " + System.getProperty( "java.version" ) + "; "
320 + System.getProperty( "os.name" ) + " " + System.getProperty( "os.version" ) + ")";
321 }
322
323 private Collection<FileTransformer> getTransformersForArtifact( final Artifact artifact,
324 final SessionData sessionData )
325 {
326 TransformerContext context = (TransformerContext) sessionData.get( TransformerContext.KEY );
327 Collection<FileTransformer> transformers = new ArrayList<>();
328
329
330 if ( "pom".equals( artifact.getExtension() ) && context != null )
331 {
332 transformers.add( new FileTransformer()
333 {
334 @Override
335 public InputStream transformData( File pomFile )
336 throws IOException, TransformException
337 {
338 try
339 {
340 return new ConsumerModelSourceTransformer().transform( pomFile.toPath(), context );
341 }
342 catch ( XmlPullParserException e )
343 {
344 throw new TransformException( e );
345 }
346 }
347
348 @Override
349 public Artifact transformArtifact( Artifact artifact )
350 {
351 return artifact;
352 }
353 } );
354 }
355 return Collections.unmodifiableCollection( transformers );
356 }
357
358 }