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
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashMap;
27 import java.util.LinkedHashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.stream.Collectors;
31
32 import org.apache.maven.RepositoryUtils;
33 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
34 import org.apache.maven.bridge.MavenRepositorySystem;
35 import org.apache.maven.eventspy.internal.EventSpyDispatcher;
36 import org.apache.maven.execution.MavenExecutionRequest;
37 import org.apache.maven.model.ModelBase;
38 import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
39 import org.apache.maven.rtinfo.RuntimeInformation;
40 import org.apache.maven.settings.Mirror;
41 import org.apache.maven.settings.Proxy;
42 import org.apache.maven.settings.Server;
43 import org.apache.maven.settings.building.SettingsProblem;
44 import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
45 import org.apache.maven.settings.crypto.SettingsDecrypter;
46 import org.apache.maven.settings.crypto.SettingsDecryptionResult;
47 import org.codehaus.plexus.configuration.PlexusConfiguration;
48 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
49 import org.codehaus.plexus.logging.Logger;
50 import org.codehaus.plexus.util.xml.Xpp3Dom;
51 import org.eclipse.aether.ConfigurationProperties;
52 import org.eclipse.aether.DefaultRepositorySystemSession;
53 import org.eclipse.aether.RepositorySystem;
54 import org.eclipse.aether.repository.LocalRepository;
55 import org.eclipse.aether.repository.LocalRepositoryManager;
56 import org.eclipse.aether.repository.RepositoryPolicy;
57 import org.eclipse.aether.repository.WorkspaceReader;
58 import org.eclipse.aether.resolution.ResolutionErrorPolicy;
59 import org.eclipse.aether.util.ConfigUtils;
60 import org.eclipse.aether.util.listener.ChainedRepositoryListener;
61 import org.eclipse.aether.util.repository.AuthenticationBuilder;
62 import org.eclipse.aether.util.repository.ChainedLocalRepositoryManager;
63 import org.eclipse.aether.util.repository.DefaultAuthenticationSelector;
64 import org.eclipse.aether.util.repository.DefaultMirrorSelector;
65 import org.eclipse.aether.util.repository.DefaultProxySelector;
66 import org.eclipse.aether.util.repository.SimpleResolutionErrorPolicy;
67 import org.eclipse.sisu.Nullable;
68
69 import static java.util.stream.Collectors.toList;
70
71
72
73
74 @Named
75 public class DefaultRepositorySystemSessionFactory {
76
77
78
79
80
81
82
83 private static final String MAVEN_REPO_LOCAL_TAIL = "maven.repo.local.tail";
84
85
86
87
88
89
90
91 private static final String MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY = "maven.repo.local.tail.ignoreAvailability";
92
93
94
95
96
97
98
99
100
101 private static final String MAVEN_REPO_LOCAL_RECORD_REVERSE_TREE = "maven.repo.local.recordReverseTree";
102
103 private static final String MAVEN_RESOLVER_TRANSPORT_KEY = "maven.resolver.transport";
104
105 private static final String MAVEN_RESOLVER_TRANSPORT_DEFAULT = "default";
106
107 private static final String MAVEN_RESOLVER_TRANSPORT_WAGON = "wagon";
108
109 private static final String MAVEN_RESOLVER_TRANSPORT_NATIVE = "native";
110
111 private static final String MAVEN_RESOLVER_TRANSPORT_AUTO = "auto";
112
113 private static final String WAGON_TRANSPORTER_PRIORITY_KEY = "aether.priority.WagonTransporterFactory";
114
115 private static final String NATIVE_HTTP_TRANSPORTER_PRIORITY_KEY = "aether.priority.HttpTransporterFactory";
116
117 private static final String NATIVE_FILE_TRANSPORTER_PRIORITY_KEY = "aether.priority.FileTransporterFactory";
118
119 private static final String RESOLVER_MAX_PRIORITY = String.valueOf(Float.MAX_VALUE);
120
121 @Inject
122 private Logger logger;
123
124 @Inject
125 private ArtifactHandlerManager artifactHandlerManager;
126
127 @Inject
128 private RepositorySystem repoSystem;
129
130 @Inject
131 @Nullable
132 @Named("ide")
133 private WorkspaceReader workspaceRepository;
134
135 @Inject
136 private SettingsDecrypter settingsDecrypter;
137
138 @Inject
139 private EventSpyDispatcher eventSpyDispatcher;
140
141 @Inject
142 MavenRepositorySystem mavenRepositorySystem;
143
144 @Inject
145 private RuntimeInformation runtimeInformation;
146
147 @SuppressWarnings("checkstyle:methodlength")
148 public DefaultRepositorySystemSession newRepositorySession(MavenExecutionRequest request) {
149 DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
150
151 session.setCache(request.getRepositoryCache());
152
153 Map<Object, Object> configProps = new LinkedHashMap<>();
154 configProps.put(ConfigurationProperties.USER_AGENT, getUserAgent());
155 configProps.put(ConfigurationProperties.INTERACTIVE, request.isInteractiveMode());
156 configProps.put("maven.startTime", request.getStartTime());
157
158 configProps.putAll(getPropertiesFromRequestedProfiles(request));
159
160 configProps.putAll(request.getSystemProperties());
161 configProps.putAll(request.getUserProperties());
162
163 session.setOffline(request.isOffline());
164 session.setChecksumPolicy(request.getGlobalChecksumPolicy());
165 if (request.isNoSnapshotUpdates()) {
166 session.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_NEVER);
167 } else if (request.isUpdateSnapshots()) {
168 session.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS);
169 } else {
170 session.setUpdatePolicy(null);
171 }
172
173 int errorPolicy = 0;
174 errorPolicy |= request.isCacheNotFound()
175 ? ResolutionErrorPolicy.CACHE_NOT_FOUND
176 : ResolutionErrorPolicy.CACHE_DISABLED;
177 errorPolicy |= request.isCacheTransferError()
178 ? ResolutionErrorPolicy.CACHE_TRANSFER_ERROR
179 : ResolutionErrorPolicy.CACHE_DISABLED;
180 session.setResolutionErrorPolicy(
181 new SimpleResolutionErrorPolicy(errorPolicy, errorPolicy | ResolutionErrorPolicy.CACHE_NOT_FOUND));
182
183 session.setArtifactTypeRegistry(RepositoryUtils.newArtifactTypeRegistry(artifactHandlerManager));
184
185 if (request.getWorkspaceReader() != null) {
186 session.setWorkspaceReader(request.getWorkspaceReader());
187 } else {
188 session.setWorkspaceReader(workspaceRepository);
189 }
190
191 DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest();
192 decrypt.setProxies(request.getProxies());
193 decrypt.setServers(request.getServers());
194 SettingsDecryptionResult decrypted = settingsDecrypter.decrypt(decrypt);
195
196 if (logger.isDebugEnabled()) {
197 for (SettingsProblem problem : decrypted.getProblems()) {
198 logger.debug(problem.getMessage(), problem.getException());
199 }
200 }
201
202 DefaultMirrorSelector mirrorSelector = new DefaultMirrorSelector();
203 for (Mirror mirror : request.getMirrors()) {
204 mirrorSelector.add(
205 mirror.getId(),
206 mirror.getUrl(),
207 mirror.getLayout(),
208 false,
209 mirror.isBlocked(),
210 mirror.getMirrorOf(),
211 mirror.getMirrorOfLayouts());
212 }
213 session.setMirrorSelector(mirrorSelector);
214
215 DefaultProxySelector proxySelector = new DefaultProxySelector();
216 for (Proxy proxy : decrypted.getProxies()) {
217 AuthenticationBuilder authBuilder = new AuthenticationBuilder();
218 authBuilder.addUsername(proxy.getUsername()).addPassword(proxy.getPassword());
219 proxySelector.add(
220 new org.eclipse.aether.repository.Proxy(
221 proxy.getProtocol(), proxy.getHost(), proxy.getPort(), authBuilder.build()),
222 proxy.getNonProxyHosts());
223 }
224 session.setProxySelector(proxySelector);
225
226 DefaultAuthenticationSelector authSelector = new DefaultAuthenticationSelector();
227 for (Server server : decrypted.getServers()) {
228 AuthenticationBuilder authBuilder = new AuthenticationBuilder();
229 authBuilder.addUsername(server.getUsername()).addPassword(server.getPassword());
230 authBuilder.addPrivateKey(server.getPrivateKey(), server.getPassphrase());
231 authSelector.add(server.getId(), authBuilder.build());
232
233 if (server.getConfiguration() != null) {
234 Xpp3Dom dom = (Xpp3Dom) server.getConfiguration();
235 for (int i = dom.getChildCount() - 1; i >= 0; i--) {
236 Xpp3Dom child = dom.getChild(i);
237 if ("wagonProvider".equals(child.getName())) {
238 dom.removeChild(i);
239 }
240 }
241
242 XmlPlexusConfiguration config = new XmlPlexusConfiguration(dom);
243 configProps.put("aether.connector.wagon.config." + server.getId(), config);
244
245
246
247
248 Map<String, String> headers = null;
249 Integer connectTimeout = null;
250 Integer requestTimeout = null;
251
252 PlexusConfiguration httpHeaders = config.getChild("httpHeaders", false);
253 if (httpHeaders != null) {
254 PlexusConfiguration[] properties = httpHeaders.getChildren("property");
255 if (properties != null && properties.length > 0) {
256 headers = new HashMap<>();
257 for (PlexusConfiguration property : properties) {
258 headers.put(
259 property.getChild("name").getValue(),
260 property.getChild("value").getValue());
261 }
262 }
263 }
264
265 PlexusConfiguration connectTimeoutXml = config.getChild("connectTimeout", false);
266 if (connectTimeoutXml != null) {
267 connectTimeout = Integer.parseInt(connectTimeoutXml.getValue());
268 } else {
269
270 PlexusConfiguration httpConfiguration = config.getChild("httpConfiguration", false);
271 if (httpConfiguration != null) {
272 PlexusConfiguration httpConfigurationAll = httpConfiguration.getChild("all", false);
273 if (httpConfigurationAll != null) {
274 connectTimeoutXml = httpConfigurationAll.getChild("connectionTimeout", false);
275 if (connectTimeoutXml != null) {
276 connectTimeout = Integer.parseInt(connectTimeoutXml.getValue());
277 logger.warn("Settings for server " + server.getId() + " uses legacy format");
278 }
279 }
280 }
281 }
282
283 PlexusConfiguration requestTimeoutXml = config.getChild("requestTimeout", false);
284 if (requestTimeoutXml != null) {
285 requestTimeout = Integer.parseInt(requestTimeoutXml.getValue());
286 } else {
287
288 PlexusConfiguration httpConfiguration = config.getChild("httpConfiguration", false);
289 if (httpConfiguration != null) {
290 PlexusConfiguration httpConfigurationAll = httpConfiguration.getChild("all", false);
291 if (httpConfigurationAll != null) {
292 requestTimeoutXml = httpConfigurationAll.getChild("readTimeout", false);
293 if (requestTimeoutXml != null) {
294 requestTimeout = Integer.parseInt(requestTimeoutXml.getValue());
295 logger.warn("Settings for server " + server.getId() + " uses legacy format");
296 }
297 }
298 }
299 }
300
301
302 if (headers != null) {
303 configProps.put(ConfigurationProperties.HTTP_HEADERS + "." + server.getId(), headers);
304 }
305
306 if (connectTimeout != null) {
307 configProps.put(ConfigurationProperties.CONNECT_TIMEOUT + "." + server.getId(), connectTimeout);
308 }
309
310 if (requestTimeout != null) {
311 configProps.put(ConfigurationProperties.REQUEST_TIMEOUT + "." + server.getId(), requestTimeout);
312 }
313 }
314
315 configProps.put("aether.connector.perms.fileMode." + server.getId(), server.getFilePermissions());
316 configProps.put("aether.connector.perms.dirMode." + server.getId(), server.getDirectoryPermissions());
317 }
318 session.setAuthenticationSelector(authSelector);
319
320 Object transport = configProps.getOrDefault(MAVEN_RESOLVER_TRANSPORT_KEY, MAVEN_RESOLVER_TRANSPORT_DEFAULT);
321 if (MAVEN_RESOLVER_TRANSPORT_DEFAULT.equals(transport)) {
322
323 } else if (MAVEN_RESOLVER_TRANSPORT_NATIVE.equals(transport)) {
324
325 configProps.put(NATIVE_FILE_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY);
326 configProps.put(NATIVE_HTTP_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY);
327 } else if (MAVEN_RESOLVER_TRANSPORT_WAGON.equals(transport)) {
328
329 configProps.put(WAGON_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY);
330 } else if (!MAVEN_RESOLVER_TRANSPORT_AUTO.equals(transport)) {
331 throw new IllegalArgumentException("Unknown resolver transport '" + transport
332 + "'. Supported transports are: " + MAVEN_RESOLVER_TRANSPORT_WAGON + ", "
333 + MAVEN_RESOLVER_TRANSPORT_NATIVE + ", " + MAVEN_RESOLVER_TRANSPORT_AUTO);
334 }
335
336 session.setUserProperties(request.getUserProperties());
337 session.setSystemProperties(request.getSystemProperties());
338 session.setConfigProperties(configProps);
339
340 session.setTransferListener(request.getTransferListener());
341
342 session.setRepositoryListener(eventSpyDispatcher.chainListener(new LoggingRepositoryListener(logger)));
343
344 session.setIgnoreArtifactDescriptorRepositories(request.isIgnoreTransitiveRepositories());
345
346 boolean recordReverseTree = ConfigUtils.getBoolean(session, false, MAVEN_REPO_LOCAL_RECORD_REVERSE_TREE);
347 if (recordReverseTree) {
348 session.setRepositoryListener(new ChainedRepositoryListener(
349 session.getRepositoryListener(), new ReverseTreeRepositoryListener()));
350 }
351
352 mavenRepositorySystem.injectMirror(request.getRemoteRepositories(), request.getMirrors());
353 mavenRepositorySystem.injectProxy(session, request.getRemoteRepositories());
354 mavenRepositorySystem.injectAuthentication(session, request.getRemoteRepositories());
355
356 mavenRepositorySystem.injectMirror(request.getPluginArtifactRepositories(), request.getMirrors());
357 mavenRepositorySystem.injectProxy(session, request.getPluginArtifactRepositories());
358 mavenRepositorySystem.injectAuthentication(session, request.getPluginArtifactRepositories());
359
360 setUpLocalRepositoryManager(request, session);
361
362 return session;
363 }
364
365 private void setUpLocalRepositoryManager(MavenExecutionRequest request, DefaultRepositorySystemSession session) {
366 LocalRepository localRepo =
367 new LocalRepository(request.getLocalRepository().getBasedir());
368
369 LocalRepositoryManager lrm = repoSystem.newLocalRepositoryManager(session, localRepo);
370
371 String localRepoTail = ConfigUtils.getString(session, null, MAVEN_REPO_LOCAL_TAIL);
372 if (localRepoTail != null) {
373 boolean ignoreTailAvailability =
374 ConfigUtils.getBoolean(session, true, MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY);
375 List<LocalRepositoryManager> tail = new ArrayList<>();
376 List<String> paths = Arrays.stream(localRepoTail.split(","))
377 .filter(p -> p != null && !p.trim().isEmpty())
378 .collect(toList());
379 for (String path : paths) {
380 tail.add(repoSystem.newLocalRepositoryManager(session, new LocalRepository(path)));
381 }
382 session.setLocalRepositoryManager(new ChainedLocalRepositoryManager(lrm, tail, ignoreTailAvailability));
383 } else {
384 session.setLocalRepositoryManager(lrm);
385 }
386 }
387
388 private Map<?, ?> getPropertiesFromRequestedProfiles(MavenExecutionRequest request) {
389
390 List<String> activeProfileId = request.getActiveProfiles();
391
392 return request.getProfiles().stream()
393 .filter(profile -> activeProfileId.contains(profile.getId()))
394 .map(ModelBase::getProperties)
395 .flatMap(properties -> properties.entrySet().stream())
396 .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (k1, k2) -> k2));
397 }
398
399 private String getUserAgent() {
400 String version = runtimeInformation.getMavenVersion();
401 version = version.isEmpty() ? version : "/" + version;
402 return "Apache-Maven" + version + " (Java " + System.getProperty("java.version") + "; "
403 + System.getProperty("os.name") + " " + System.getProperty("os.version") + ")";
404 }
405 }