1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.internal.aether;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.HashMap;
30 import java.util.LinkedHashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34 import java.util.stream.Collectors;
35
36 import org.apache.maven.RepositoryUtils;
37 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
38 import org.apache.maven.artifact.repository.ArtifactRepository;
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.internal.RepositorySystemSessionFactory;
43 import org.apache.maven.model.ModelBase;
44 import org.apache.maven.repository.supplier.SessionBuilderSupplier;
45 import org.apache.maven.rtinfo.RuntimeInformation;
46 import org.apache.maven.settings.Mirror;
47 import org.apache.maven.settings.Proxy;
48 import org.apache.maven.settings.Server;
49 import org.apache.maven.settings.building.SettingsProblem;
50 import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
51 import org.apache.maven.settings.crypto.SettingsDecrypter;
52 import org.apache.maven.settings.crypto.SettingsDecryptionResult;
53 import org.codehaus.plexus.configuration.PlexusConfiguration;
54 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
55 import org.codehaus.plexus.logging.Logger;
56 import org.codehaus.plexus.util.xml.Xpp3Dom;
57 import org.eclipse.aether.ConfigurationProperties;
58 import org.eclipse.aether.DefaultRepositorySystemSession;
59 import org.eclipse.aether.RepositorySystem;
60 import org.eclipse.aether.RepositorySystemSession;
61 import org.eclipse.aether.collection.VersionFilterBuilder;
62 import org.eclipse.aether.repository.AuthenticationSelector;
63 import org.eclipse.aether.repository.LocalRepository;
64 import org.eclipse.aether.repository.LocalRepositoryManager;
65 import org.eclipse.aether.repository.RepositoryPolicy;
66 import org.eclipse.aether.repository.WorkspaceReader;
67 import org.eclipse.aether.resolution.ResolutionErrorPolicy;
68 import org.eclipse.aether.util.ConfigUtils;
69 import org.eclipse.aether.util.graph.manager.TransitiveDependencyManager;
70 import org.eclipse.aether.util.listener.ChainedRepositoryListener;
71 import org.eclipse.aether.util.repository.AuthenticationBuilder;
72 import org.eclipse.aether.util.repository.ChainedLocalRepositoryManager;
73 import org.eclipse.aether.util.repository.DefaultAuthenticationSelector;
74 import org.eclipse.aether.util.repository.DefaultMirrorSelector;
75 import org.eclipse.aether.util.repository.DefaultProxySelector;
76 import org.eclipse.aether.util.repository.SimpleResolutionErrorPolicy;
77 import org.eclipse.aether.util.version.GenericVersionScheme;
78 import org.eclipse.aether.version.InvalidVersionSpecificationException;
79 import org.eclipse.aether.version.VersionConstraint;
80 import org.eclipse.sisu.Nullable;
81
82
83
84
85 @Singleton
86 @Named
87 public class DefaultRepositorySystemSessionFactory implements RepositorySystemSessionFactory {
88
89
90
91
92
93
94
95 private static final String MAVEN_REPO_LOCAL_TAIL = "maven.repo.local.tail";
96
97
98
99
100
101
102
103
104
105 public static final String MAVEN_REPO_LOCAL_HEAD = "maven.repo.local.head";
106
107
108
109
110
111
112
113 private static final String MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY = "maven.repo.local.tail.ignoreAvailability";
114
115
116
117
118
119
120
121
122
123 private static final String MAVEN_REPO_LOCAL_RECORD_REVERSE_TREE = "maven.repo.local.recordReverseTree";
124
125
126
127
128
129
130
131
132 private static final String MAVEN_VERSION_FILTER = "maven.session.versionFilter";
133
134
135
136
137
138
139
140
141
142
143
144 public static final String MAVEN_RESOLVER_DEPENDENCY_MANAGER_TRANSITIVITY =
145 "maven.resolver.dependencyManagerTransitivity";
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168 public static final String MAVEN_REPOSITORY_CREDENTIAL_SCOPE = "maven.repository.credentialScope";
169
170 private static final String MAVEN_RESOLVER_TRANSPORT_KEY = "maven.resolver.transport";
171
172 private static final String MAVEN_RESOLVER_TRANSPORT_DEFAULT = "default";
173
174 private static final String MAVEN_RESOLVER_TRANSPORT_WAGON = "wagon";
175
176 private static final String MAVEN_RESOLVER_TRANSPORT_APACHE = "native";
177
178 private static final String MAVEN_RESOLVER_TRANSPORT_AUTO = "auto";
179
180 private static final String WAGON_TRANSPORTER_PRIORITY_KEY = "aether.priority.WagonTransporterFactory";
181
182 private static final String APACHE_HTTP_TRANSPORTER_PRIORITY_KEY = "aether.priority.ApacheTransporterFactory";
183
184 private static final String FILE_TRANSPORTER_PRIORITY_KEY = "aether.priority.FileTransporterFactory";
185
186 private static final String RESOLVER_MAX_PRIORITY = String.valueOf(Float.MAX_VALUE);
187
188 @Inject
189 private Logger logger;
190
191 @Inject
192 private ArtifactHandlerManager artifactHandlerManager;
193
194 @Inject
195 private RepositorySystem repoSystem;
196
197 @Inject
198 @Nullable
199 @Named("ide")
200 private WorkspaceReader workspaceRepository;
201
202 @Inject
203 private SettingsDecrypter settingsDecrypter;
204
205 @Inject
206 private EventSpyDispatcher eventSpyDispatcher;
207
208 @Inject
209 private MavenRepositorySystem mavenRepositorySystem;
210
211 @Inject
212 private RuntimeInformation runtimeInformation;
213
214 @Inject
215 private VersionFilterBuilder versionFilterBuilder;
216
217 private final GenericVersionScheme versionScheme = new GenericVersionScheme();
218
219
220
221
222 @Deprecated
223 public DefaultRepositorySystemSession newRepositorySession(MavenExecutionRequest request) {
224 return new DefaultRepositorySystemSession(
225 newRepositorySessionBuilder(request).build());
226 }
227
228 @SuppressWarnings("checkstyle:methodlength")
229 @Override
230 public RepositorySystemSession.SessionBuilder newRepositorySessionBuilder(MavenExecutionRequest request) {
231
232 Map<Object, Object> configProps = new LinkedHashMap<>();
233 configProps.put(ConfigurationProperties.USER_AGENT, getUserAgent());
234 configProps.put(ConfigurationProperties.INTERACTIVE, request.isInteractiveMode());
235 configProps.put("maven.startTime", request.getStartTime());
236
237 configProps.putAll(getPropertiesFromRequestedProfiles(request));
238
239 configProps.putAll(request.getSystemProperties());
240 configProps.putAll(request.getUserProperties());
241
242 RepositorySystemSession.SessionBuilder mainSessionBuilder = new SessionBuilderSupplier(repoSystem).get();
243 mainSessionBuilder.setCache(request.getRepositoryCache());
244
245 mainSessionBuilder.setOffline(request.isOffline());
246 mainSessionBuilder.setChecksumPolicy(request.getGlobalChecksumPolicy());
247
248 if (request.getArtifactsUpdatePolicy() == null && request.getMetadataUpdatePolicy() == null) {
249
250 if (request.isNoSnapshotUpdates()) {
251 mainSessionBuilder.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_NEVER);
252 } else if (request.isUpdateSnapshots()) {
253 mainSessionBuilder.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS);
254 } else {
255 mainSessionBuilder.setUpdatePolicy(null);
256 }
257 } else {
258
259 if (request.getArtifactsUpdatePolicy() != null) {
260 mainSessionBuilder.setArtifactUpdatePolicy(request.getArtifactsUpdatePolicy());
261 }
262 if (request.getMetadataUpdatePolicy() != null) {
263 mainSessionBuilder.setMetadataUpdatePolicy(request.getMetadataUpdatePolicy());
264 }
265 }
266
267 int errorPolicy = 0;
268 errorPolicy |= request.isCacheNotFound()
269 ? ResolutionErrorPolicy.CACHE_NOT_FOUND
270 : ResolutionErrorPolicy.CACHE_DISABLED;
271 errorPolicy |= request.isCacheTransferError()
272 ? ResolutionErrorPolicy.CACHE_TRANSFER_ERROR
273 : ResolutionErrorPolicy.CACHE_DISABLED;
274 mainSessionBuilder.setResolutionErrorPolicy(
275 new SimpleResolutionErrorPolicy(errorPolicy, errorPolicy | ResolutionErrorPolicy.CACHE_NOT_FOUND));
276
277 mainSessionBuilder.setArtifactTypeRegistry(RepositoryUtils.newArtifactTypeRegistry(artifactHandlerManager));
278
279 if (request.getWorkspaceReader() != null) {
280 mainSessionBuilder.setWorkspaceReader(request.getWorkspaceReader());
281 } else {
282 mainSessionBuilder.setWorkspaceReader(workspaceRepository);
283 }
284
285 DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest();
286 decrypt.setProxies(request.getProxies());
287 decrypt.setServers(request.getServers());
288 SettingsDecryptionResult decrypted = settingsDecrypter.decrypt(decrypt);
289
290 if (logger.isDebugEnabled()) {
291 for (SettingsProblem problem : decrypted.getProblems()) {
292 logger.debug(problem.getMessage(), problem.getException());
293 }
294 }
295
296 versionFilterBuilder
297 .buildVersionFilter((String) configProps.get(MAVEN_VERSION_FILTER), this::parseVersionConstraint)
298 .ifPresent(mainSessionBuilder::setVersionFilter);
299
300 boolean dependencyManagerTransitivity =
301 ConfigUtils.getBoolean(configProps, false, MAVEN_RESOLVER_DEPENDENCY_MANAGER_TRANSITIVITY);
302 if (dependencyManagerTransitivity) {
303 mainSessionBuilder.setDependencyManager(new TransitiveDependencyManager());
304 }
305
306
307
308
309 Map<String, Set<String>> declaredRepositoryOrigins = new HashMap<>();
310
311 DefaultMirrorSelector mirrorSelector = new DefaultMirrorSelector();
312 for (Mirror mirror : request.getMirrors()) {
313 mirrorSelector.add(
314 mirror.getId(),
315 mirror.getUrl(),
316 mirror.getLayout(),
317 false,
318 mirror.isBlocked(),
319 mirror.getMirrorOf(),
320 mirror.getMirrorOfLayouts());
321 OriginBoundAuthenticationSelector.addOrigin(declaredRepositoryOrigins, mirror.getId(), mirror.getUrl());
322 }
323 mainSessionBuilder.setMirrorSelector(mirrorSelector);
324 for (ArtifactRepository repository : request.getRemoteRepositories()) {
325 OriginBoundAuthenticationSelector.addOrigin(
326 declaredRepositoryOrigins, repository.getId(), repository.getUrl());
327 }
328 for (ArtifactRepository repository : request.getPluginArtifactRepositories()) {
329 OriginBoundAuthenticationSelector.addOrigin(
330 declaredRepositoryOrigins, repository.getId(), repository.getUrl());
331 }
332
333 DefaultProxySelector proxySelector = new DefaultProxySelector();
334 for (Proxy proxy : decrypted.getProxies()) {
335 AuthenticationBuilder authBuilder = new AuthenticationBuilder();
336 authBuilder.addUsername(proxy.getUsername()).addPassword(proxy.getPassword());
337 proxySelector.add(
338 new org.eclipse.aether.repository.Proxy(
339 proxy.getProtocol(), proxy.getHost(), proxy.getPort(), authBuilder.build()),
340 proxy.getNonProxyHosts());
341 }
342 mainSessionBuilder.setProxySelector(proxySelector);
343
344 DefaultAuthenticationSelector authSelector = new DefaultAuthenticationSelector();
345 for (Server server : decrypted.getServers()) {
346 AuthenticationBuilder authBuilder = new AuthenticationBuilder();
347 authBuilder.addUsername(server.getUsername()).addPassword(server.getPassword());
348 authBuilder.addPrivateKey(server.getPrivateKey(), server.getPassphrase());
349 authSelector.add(server.getId(), authBuilder.build());
350
351
352
353 for (String repositoryOrigin : server.getRepositoryOrigins()) {
354 OriginBoundAuthenticationSelector.addOrigin(
355 declaredRepositoryOrigins, server.getId(), repositoryOrigin);
356 }
357
358 if (server.getConfiguration() != null) {
359 Xpp3Dom dom = (Xpp3Dom) server.getConfiguration();
360 for (int i = dom.getChildCount() - 1; i >= 0; i--) {
361 Xpp3Dom child = dom.getChild(i);
362 if ("wagonProvider".equals(child.getName())) {
363 dom.removeChild(i);
364 }
365 }
366
367 XmlPlexusConfiguration config = new XmlPlexusConfiguration(dom);
368 configProps.put("aether.transport.wagon.config." + server.getId(), config);
369
370
371
372
373 Map<String, String> headers = null;
374 Integer connectTimeout = null;
375 Integer requestTimeout = null;
376
377 PlexusConfiguration httpHeaders = config.getChild("httpHeaders", false);
378 if (httpHeaders != null) {
379 PlexusConfiguration[] properties = httpHeaders.getChildren("property");
380 if (properties != null && properties.length > 0) {
381 headers = new HashMap<>();
382 for (PlexusConfiguration property : properties) {
383 headers.put(
384 property.getChild("name").getValue(),
385 property.getChild("value").getValue());
386 }
387 }
388 }
389
390 PlexusConfiguration connectTimeoutXml = config.getChild("connectTimeout", false);
391 if (connectTimeoutXml != null) {
392 connectTimeout = Integer.parseInt(connectTimeoutXml.getValue());
393 } else {
394
395 PlexusConfiguration httpConfiguration = config.getChild("httpConfiguration", false);
396 if (httpConfiguration != null) {
397 PlexusConfiguration httpConfigurationAll = httpConfiguration.getChild("all", false);
398 if (httpConfigurationAll != null) {
399 connectTimeoutXml = httpConfigurationAll.getChild("connectionTimeout", false);
400 if (connectTimeoutXml != null) {
401 connectTimeout = Integer.parseInt(connectTimeoutXml.getValue());
402 logger.warn("Settings for server " + server.getId() + " uses legacy format");
403 }
404 }
405 }
406 }
407
408 PlexusConfiguration requestTimeoutXml = config.getChild("requestTimeout", false);
409 if (requestTimeoutXml != null) {
410 requestTimeout = Integer.parseInt(requestTimeoutXml.getValue());
411 } else {
412
413 PlexusConfiguration httpConfiguration = config.getChild("httpConfiguration", false);
414 if (httpConfiguration != null) {
415 PlexusConfiguration httpConfigurationAll = httpConfiguration.getChild("all", false);
416 if (httpConfigurationAll != null) {
417 requestTimeoutXml = httpConfigurationAll.getChild("readTimeout", false);
418 if (requestTimeoutXml != null) {
419 requestTimeout = Integer.parseInt(requestTimeoutXml.getValue());
420 logger.warn("Settings for server " + server.getId() + " uses legacy format");
421 }
422 }
423 }
424 }
425
426
427 if (headers != null) {
428 configProps.put(ConfigurationProperties.HTTP_HEADERS + "." + server.getId(), headers);
429 }
430
431 if (connectTimeout != null) {
432 configProps.put(ConfigurationProperties.CONNECT_TIMEOUT + "." + server.getId(), connectTimeout);
433 }
434
435 if (requestTimeout != null) {
436 configProps.put(ConfigurationProperties.REQUEST_TIMEOUT + "." + server.getId(), requestTimeout);
437 }
438 }
439
440 configProps.put("aether.transport.wagon.perms.fileMode." + server.getId(), server.getFilePermissions());
441 configProps.put("aether.transport.wagon.perms.dirMode." + server.getId(), server.getDirectoryPermissions());
442 }
443 String credentialScope = ConfigUtils.getString(
444 configProps, OriginBoundAuthenticationSelector.SCOPE_ORIGIN, MAVEN_REPOSITORY_CREDENTIAL_SCOPE);
445 AuthenticationSelector effectiveAuthSelector = OriginBoundAuthenticationSelector.wrap(
446 authSelector, credentialScope, declaredRepositoryOrigins, logger);
447 mainSessionBuilder.setAuthenticationSelector(effectiveAuthSelector);
448
449 Object transport = configProps.getOrDefault(MAVEN_RESOLVER_TRANSPORT_KEY, MAVEN_RESOLVER_TRANSPORT_DEFAULT);
450 if (MAVEN_RESOLVER_TRANSPORT_DEFAULT.equals(transport)) {
451
452 } else if (MAVEN_RESOLVER_TRANSPORT_APACHE.equals(transport)) {
453
454 configProps.put(FILE_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY);
455 configProps.put(APACHE_HTTP_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY);
456 } else if (MAVEN_RESOLVER_TRANSPORT_WAGON.equals(transport)) {
457
458 configProps.put(WAGON_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY);
459 } else if (!MAVEN_RESOLVER_TRANSPORT_AUTO.equals(transport)) {
460 throw new IllegalArgumentException("Unknown resolver transport '" + transport
461 + "'. Supported transports are: " + MAVEN_RESOLVER_TRANSPORT_WAGON + ", "
462 + MAVEN_RESOLVER_TRANSPORT_APACHE + ", " + MAVEN_RESOLVER_TRANSPORT_AUTO);
463 }
464
465 mainSessionBuilder.setUserProperties(request.getUserProperties());
466 mainSessionBuilder.setSystemProperties(request.getSystemProperties());
467 mainSessionBuilder.setConfigProperties(configProps);
468
469 mainSessionBuilder.setTransferListener(request.getTransferListener());
470
471 mainSessionBuilder.setRepositoryListener(
472 eventSpyDispatcher.chainListener(new LoggingRepositoryListener(logger)));
473
474 mainSessionBuilder.setIgnoreArtifactDescriptorRepositories(request.isIgnoreTransitiveRepositories());
475
476 try (RepositorySystemSession.CloseableSession protoSession =
477 setUpLocalRepositoryManager(request, repoSystem, mainSessionBuilder)) {
478 boolean recordReverseTree =
479 ConfigUtils.getBoolean(protoSession, false, MAVEN_REPO_LOCAL_RECORD_REVERSE_TREE);
480 if (recordReverseTree) {
481 mainSessionBuilder.setRepositoryListener(new ChainedRepositoryListener(
482 protoSession.getRepositoryListener(), new ReverseTreeRepositoryListener()));
483 }
484
485 mavenRepositorySystem.injectMirror(request.getRemoteRepositories(), request.getMirrors());
486 mavenRepositorySystem.injectProxy(protoSession, request.getRemoteRepositories());
487 mavenRepositorySystem.injectAuthentication(protoSession, request.getRemoteRepositories());
488
489 mavenRepositorySystem.injectMirror(request.getPluginArtifactRepositories(), request.getMirrors());
490 mavenRepositorySystem.injectProxy(protoSession, request.getPluginArtifactRepositories());
491 mavenRepositorySystem.injectAuthentication(protoSession, request.getPluginArtifactRepositories());
492
493 return mainSessionBuilder;
494 }
495 }
496
497 private static RepositorySystemSession.CloseableSession setUpLocalRepositoryManager(
498 MavenExecutionRequest request,
499 RepositorySystem repoSystem,
500 RepositorySystemSession.SessionBuilder sessionBuilder) {
501 Path requestLocalRepositoryPath = resolve(request.getLocalRepository().getBasedir());
502 RepositorySystemSession.CloseableSession protoSession = sessionBuilder
503 .withLocalRepositoryBaseDirectories(requestLocalRepositoryPath)
504 .build();
505 LocalRepositoryManager lrm =
506 setUpLocalRepositoryManager(request.getLocalRepository().getBasedir(), repoSystem, protoSession);
507 sessionBuilder.setLocalRepositoryManager(lrm);
508 return protoSession;
509 }
510
511 public static LocalRepositoryManager setUpLocalRepositoryManager(
512 String localRepository, RepositorySystem repoSystem, RepositorySystemSession session) {
513 List<Path> paths = new ArrayList<>();
514 String localRepoHead = ConfigUtils.getString(session, null, MAVEN_REPO_LOCAL_HEAD);
515 if (localRepoHead != null) {
516 Arrays.stream(localRepoHead.split(","))
517 .filter(p -> !p.trim().isEmpty())
518 .map(DefaultRepositorySystemSessionFactory::resolve)
519 .forEach(paths::add);
520 }
521
522 paths.add(resolve(localRepository));
523
524 String localRepoTail = ConfigUtils.getString(session, null, MAVEN_REPO_LOCAL_TAIL);
525 if (localRepoTail != null) {
526 Arrays.stream(localRepoTail.split(","))
527 .filter(p -> !p.trim().isEmpty())
528 .map(DefaultRepositorySystemSessionFactory::resolve)
529 .forEach(paths::add);
530 }
531
532 LocalRepository localRepo = new LocalRepository(paths.remove(0));
533 LocalRepositoryManager lrm = repoSystem.newLocalRepositoryManager(session, localRepo);
534
535 if (!paths.isEmpty()) {
536 List<LocalRepositoryManager> tail = new ArrayList<>();
537 for (Path path : paths) {
538 tail.add(repoSystem.newLocalRepositoryManager(session, new LocalRepository(path)));
539 }
540 boolean ignoreTailAvailability =
541 ConfigUtils.getBoolean(session, true, MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY);
542
543 lrm = new ChainedLocalRepositoryManager(lrm, tail, ignoreTailAvailability);
544 }
545 return lrm;
546 }
547
548 public static Path resolve(String string) {
549 if (string.startsWith("~/") || string.startsWith("~\\")) {
550
551 return Paths.get(System.getProperty("user.home"))
552 .resolve(string.substring(2))
553 .normalize()
554 .toAbsolutePath();
555 } else {
556
557 return Paths.get(string).normalize().toAbsolutePath();
558 }
559 }
560
561 private VersionConstraint parseVersionConstraint(String spec) {
562 try {
563 return versionScheme.parseVersionConstraint(spec);
564 } catch (InvalidVersionSpecificationException e) {
565 throw new RuntimeException(e);
566 }
567 }
568
569 private Map<?, ?> getPropertiesFromRequestedProfiles(MavenExecutionRequest request) {
570
571 List<String> activeProfileId = request.getActiveProfiles();
572 List<String> inactiveProfileId = request.getInactiveProfiles();
573
574 return request.getProfiles().stream()
575 .filter(profile -> activeProfileId.contains(profile.getId())
576 || (!inactiveProfileId.contains(profile.getId())
577 && profile.getActivation() != null
578 && profile.getActivation().isActiveByDefault()))
579 .map(ModelBase::getProperties)
580 .flatMap(properties -> properties.entrySet().stream())
581 .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (k1, k2) -> k2));
582 }
583
584 private String getUserAgent() {
585 String version = runtimeInformation.getMavenVersion();
586 version = version.isEmpty() ? version : "/" + version;
587 return "Apache-Maven" + version + " (Java " + System.getProperty("java.version") + "; "
588 + System.getProperty("os.name") + " " + System.getProperty("os.version") + ")";
589 }
590 }