From e89b6fd53f320f31a0f2b3ce4e3ae1837cd4e081 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Tue, 21 Nov 2023 12:04:01 +0100 Subject: [PATCH] [MNG-7653] Integrate Resolver 2.x onSessionClose (#1301) Implement onSessionClose and "resolver 2.x way for sessions"... As digging happens in same area, some other "resolver configuration" issues resolved as well. Important: contains a "hack" to fix issue in alpha-2, that is marked with TODO to remove once alpha-3+ used. --- https://issues.apache.org/jira/browse/MNG-7653 https://issues.apache.org/jira/browse/MNG-7935 https://issues.apache.org/jira/browse/MNG-7936 --- .../java/org/apache/maven/DefaultMaven.java | 41 +++- .../DefaultMavenExecutionRequest.java | 28 +++ .../execution/MavenExecutionRequest.java | 20 ++ .../apache/maven/execution/MavenSession.java | 49 +++-- ...DefaultRepositorySystemSessionFactory.java | 208 +++++++++++++----- .../maven/internal/impl/DefaultSession.java | 4 +- ...ultRepositorySystemSessionFactoryTest.java | 10 - .../apache/maven/internal/impl/TestApi.java | 4 +- .../java/org/apache/maven/cli/CLIManager.java | 15 ++ .../java/org/apache/maven/cli/MavenCli.java | 13 +- .../BootstrapCoreExtensionManager.java | 12 +- .../internal/MavenRepositorySystemUtils.java | 48 ++++ pom.xml | 2 +- 13 files changed, 360 insertions(+), 94 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java index c148261aaa..19475a8af8 100644 --- a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java +++ b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java @@ -36,6 +36,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.util.stream.Stream; @@ -73,8 +74,8 @@ import org.apache.maven.project.ProjectBuilder; import org.apache.maven.session.scope.internal.SessionScope; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; -import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.RepositorySystemSession.CloseableSession; import org.eclipse.aether.repository.WorkspaceReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -214,9 +215,9 @@ public class DefaultMaven implements Maven { // so that @SessionScoped components can be @Injected into AbstractLifecycleParticipants. // sessionScope.enter(); - try { - DefaultRepositorySystemSession repoSession = (DefaultRepositorySystemSession) newRepositorySession(request); - MavenSession session = new MavenSession(container, repoSession, request, result); + try (CloseableSession closeableSession = newCloseableSession(request)) { + AtomicReference closeableSessionRef = new AtomicReference<>(closeableSession); + MavenSession session = new MavenSession(closeableSessionRef::get, request, result); session.setSession(defaultSessionFactory.getSession(session)); sessionScope.seed(MavenSession.class, session); @@ -225,7 +226,7 @@ public class DefaultMaven implements Maven { legacySupport.setSession(session); - return doExecute(request, session, result, repoSession); + return doExecute(request, session, result, closeableSessionRef); } finally { sessionScope.exit(); } @@ -235,7 +236,7 @@ public class DefaultMaven implements Maven { MavenExecutionRequest request, MavenSession session, MavenExecutionResult result, - DefaultRepositorySystemSession repoSession) { + AtomicReference closeableSessionRef) { try { afterSessionStart(session); } catch (MavenExecutionException e) { @@ -244,7 +245,11 @@ public class DefaultMaven implements Maven { try { WorkspaceReader reactorReader = container.lookup(WorkspaceReader.class, ReactorReader.HINT); - repoSession.setWorkspaceReader(reactorReader); + closeableSessionRef.set(closeableSessionRef + .get() + .copy() + .setWorkspaceReader(reactorReader) + .build()); } catch (ComponentLookupException e) { return addExceptionToResult(result, e); } @@ -265,11 +270,10 @@ public class DefaultMaven implements Maven { } try { - setupWorkspaceReader(session, repoSession); + closeableSessionRef.set(setupWorkspaceReader(session, closeableSessionRef.get())); } catch (ComponentLookupException e) { return addExceptionToResult(result, e); } - repoSession.setReadOnly(); try { afterProjectsRead(session); } catch (MavenExecutionException e) { @@ -336,7 +340,7 @@ public class DefaultMaven implements Maven { return result; } - private void setupWorkspaceReader(MavenSession session, DefaultRepositorySystemSession repoSession) + private CloseableSession setupWorkspaceReader(MavenSession session, CloseableSession repoSession) throws ComponentLookupException { // Desired order of precedence for workspace readers before querying the local artifact repositories Set workspaceReaders = new LinkedHashSet<>(); @@ -350,7 +354,10 @@ public class DefaultMaven implements Maven { } // 3) .. n) Project-scoped workspace readers workspaceReaders.addAll(getProjectScopedExtensionComponents(session.getProjects(), WorkspaceReader.class)); - repoSession.setWorkspaceReader(MavenChainedWorkspaceReader.of(workspaceReaders)); + return repoSession + .copy() + .setWorkspaceReader(MavenChainedWorkspaceReader.of(workspaceReaders)) + .build(); } private void afterSessionStart(MavenSession session) throws MavenExecutionException { @@ -404,8 +411,18 @@ public class DefaultMaven implements Maven { } } + /** + * Nobody should ever use this method. + * + * @deprecated If you use this method and your code is not in Maven Core, stop doing this. + */ + @Deprecated public RepositorySystemSession newRepositorySession(MavenExecutionRequest request) { - return repositorySessionFactory.newRepositorySession(request); + return newCloseableSession(request); + } + + private CloseableSession newCloseableSession(MavenExecutionRequest request) { + return repositorySessionFactory.newRepositorySessionBuilder(request).build(); } private void validateLocalRepository(MavenExecutionRequest request) throws IOException { diff --git a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java index d48fa180b1..7f2bb95362 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java +++ b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java @@ -66,6 +66,10 @@ public class DefaultMavenExecutionRequest implements MavenExecutionRequest { private boolean cacheNotFound = false; + private boolean ignoreMissingArtifactDescriptor = true; + + private boolean ignoreInvalidArtifactDescriptor = true; + private List proxies; private List servers; @@ -174,6 +178,8 @@ public class DefaultMavenExecutionRequest implements MavenExecutionRequest { copy.setInteractiveMode(original.isInteractiveMode()); copy.setCacheNotFound(original.isCacheNotFound()); copy.setCacheTransferError(original.isCacheTransferError()); + copy.setIgnoreMissingArtifactDescriptor(original.isIgnoreMissingArtifactDescriptor()); + copy.setIgnoreInvalidArtifactDescriptor(original.isIgnoreInvalidArtifactDescriptor()); copy.setProxies(original.getProxies()); copy.setServers(original.getServers()); copy.setMirrors(original.getMirrors()); @@ -1034,6 +1040,28 @@ public class DefaultMavenExecutionRequest implements MavenExecutionRequest { return this; } + @Override + public boolean isIgnoreMissingArtifactDescriptor() { + return ignoreMissingArtifactDescriptor; + } + + @Override + public MavenExecutionRequest setIgnoreMissingArtifactDescriptor(boolean ignoreMissing) { + this.ignoreMissingArtifactDescriptor = ignoreMissing; + return this; + } + + @Override + public boolean isIgnoreInvalidArtifactDescriptor() { + return ignoreInvalidArtifactDescriptor; + } + + @Override + public MavenExecutionRequest setIgnoreInvalidArtifactDescriptor(boolean ignoreInvalid) { + this.ignoreInvalidArtifactDescriptor = ignoreInvalid; + return this; + } + @Override public boolean isUseLegacyLocalRepository() { return this.useLegacyLocalRepositoryManager; diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java index fedc394d84..c5bcb6a7a7 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java +++ b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java @@ -285,6 +285,26 @@ public interface MavenExecutionRequest { MavenExecutionRequest setCacheNotFound(boolean cacheNotFound); + /** + * @since 4.0.0 + */ + boolean isIgnoreMissingArtifactDescriptor(); + + /** + * @since 4.0.0 + */ + MavenExecutionRequest setIgnoreMissingArtifactDescriptor(boolean ignoreMissing); + + /** + * @since 4.0.0 + */ + boolean isIgnoreInvalidArtifactDescriptor(); + + /** + * @since 4.0.0 + */ + MavenExecutionRequest setIgnoreInvalidArtifactDescriptor(boolean ignoreInvalid); + // Profiles List getProfiles(); diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java index 7776534542..6e1818b7fa 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java +++ b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java @@ -27,6 +27,7 @@ import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.function.Supplier; import java.util.stream.Collectors; import org.apache.maven.api.Session; @@ -46,18 +47,20 @@ import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.eclipse.aether.RepositorySystemSession; +import static java.util.Objects.requireNonNull; + /** * A Maven execution session. * */ public class MavenSession implements Cloneable { - private MavenExecutionRequest request; + private final MavenExecutionRequest request; - private MavenExecutionResult result; + private final MavenExecutionResult result; - private RepositorySystemSession repositorySession; + private final Supplier repositorySystemSessionSupplier; - private Properties executionProperties; + private final Properties executionProperties; private ThreadLocal currentProject = new ThreadLocal<>(); @@ -257,7 +260,7 @@ public class MavenSession implements Cloneable { } public RepositorySystemSession getRepositorySession() { - return repositorySession; + return repositorySystemSessionSupplier.get(); } private Map projectMap; @@ -282,7 +285,7 @@ public class MavenSession implements Cloneable { // Deprecated // - private PlexusContainer container; + private final PlexusContainer container; private final Settings settings; @@ -294,6 +297,21 @@ public class MavenSession implements Cloneable { return projectMap; } + public MavenSession( + Supplier repositorySystemSessionSupplier, + MavenExecutionRequest request, + MavenExecutionResult result) { + this.container = null; + this.request = requireNonNull(request); + this.result = requireNonNull(result); + this.settings = adaptSettings(request); + this.repositorySystemSessionSupplier = requireNonNull(repositorySystemSessionSupplier); + Properties executionProperties = new Properties(); + executionProperties.putAll(request.getSystemProperties()); + executionProperties.putAll(request.getUserProperties()); + this.executionProperties = executionProperties; + } + @Deprecated public MavenSession( PlexusContainer container, @@ -304,7 +322,11 @@ public class MavenSession implements Cloneable { this.request = request; this.result = result; this.settings = adaptSettings(request); - this.repositorySession = repositorySession; + this.repositorySystemSessionSupplier = () -> repositorySession; + Properties executionProperties = new Properties(); + executionProperties.putAll(request.getSystemProperties()); + executionProperties.putAll(request.getUserProperties()); + this.executionProperties = executionProperties; } @Deprecated @@ -363,6 +385,8 @@ public class MavenSession implements Cloneable { this.request.setGoals(goals); this.request.setBaseDirectory((executionRootDir != null) ? new File(executionRootDir) : null); this.request.setStartTime(startTime); + this.result = null; + this.repositorySystemSessionSupplier = () -> null; } @Deprecated @@ -375,7 +399,12 @@ public class MavenSession implements Cloneable { this.request = request; this.result = result; this.settings = adaptSettings(request); + Properties executionProperties = new Properties(); + executionProperties.putAll(request.getSystemProperties()); + executionProperties.putAll(request.getUserProperties()); + this.executionProperties = executionProperties; setProjects(projects); + this.repositorySystemSessionSupplier = () -> null; } /** @@ -431,12 +460,6 @@ public class MavenSession implements Cloneable { */ @Deprecated public Properties getExecutionProperties() { - if (executionProperties == null) { - executionProperties = new Properties(); - executionProperties.putAll(request.getSystemProperties()); - executionProperties.putAll(request.getUserProperties()); - } - return executionProperties; } diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java index a0e29f1d81..e17ab7c54b 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java @@ -21,8 +21,10 @@ package org.apache.maven.internal.aether; import javax.inject.Inject; import javax.inject.Named; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -33,6 +35,8 @@ import java.util.stream.Collectors; import org.apache.maven.RepositoryUtils; import org.apache.maven.api.xml.XmlNode; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.repository.Authentication; import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.eventspy.internal.EventSpyDispatcher; import org.apache.maven.execution.MavenExecutionRequest; @@ -50,27 +54,29 @@ import org.apache.maven.settings.crypto.SettingsDecrypter; import org.apache.maven.settings.crypto.SettingsDecryptionResult; import org.codehaus.plexus.configuration.PlexusConfiguration; import org.eclipse.aether.ConfigurationProperties; -import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositoryListener; import org.eclipse.aether.RepositorySystem; -import org.eclipse.aether.repository.LocalRepository; -import org.eclipse.aether.repository.LocalRepositoryManager; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.RepositorySystemSession.SessionBuilder; +import org.eclipse.aether.repository.AuthenticationContext; +import org.eclipse.aether.repository.AuthenticationSelector; +import org.eclipse.aether.repository.ProxySelector; +import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.repository.RepositoryPolicy; import org.eclipse.aether.repository.WorkspaceReader; import org.eclipse.aether.resolution.ResolutionErrorPolicy; -import org.eclipse.aether.util.ConfigUtils; import org.eclipse.aether.util.listener.ChainedRepositoryListener; import org.eclipse.aether.util.repository.AuthenticationBuilder; import org.eclipse.aether.util.repository.ChainedLocalRepositoryManager; import org.eclipse.aether.util.repository.DefaultAuthenticationSelector; import org.eclipse.aether.util.repository.DefaultMirrorSelector; import org.eclipse.aether.util.repository.DefaultProxySelector; +import org.eclipse.aether.util.repository.SimpleArtifactDescriptorPolicy; import org.eclipse.aether.util.repository.SimpleResolutionErrorPolicy; import org.eclipse.sisu.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static java.util.stream.Collectors.toList; - /** * @since 3.3.0 */ @@ -90,7 +96,9 @@ public class DefaultRepositorySystemSessionFactory { * Default: {@code true}, will ignore availability from tail local repositories. * * @since 3.9.0 + * @deprecated Use {@link ChainedLocalRepositoryManager#IGNORE_TAIL_AVAILABILITY} instead. */ + @Deprecated private static final String MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY = "maven.repo.local.tail.ignoreAvailability"; /** @@ -129,7 +137,7 @@ public class DefaultRepositorySystemSessionFactory { private static final String JDK_HTTP_TRANSPORTER_PRIORITY_KEY = "aether.priority.JdkTransporterFactory"; - private static final String NATIVE_FILE_TRANSPORTER_PRIORITY_KEY = "aether.priority.FileTransporterFactory"; + private static final String FILE_TRANSPORTER_PRIORITY_KEY = "aether.priority.FileTransporterFactory"; private static final String RESOLVER_MAX_PRIORITY = String.valueOf(Float.MAX_VALUE); @@ -145,8 +153,6 @@ public class DefaultRepositorySystemSessionFactory { private final EventSpyDispatcher eventSpyDispatcher; - private final MavenRepositorySystem mavenRepositorySystem; - private final RuntimeInformation runtimeInformation; @SuppressWarnings("checkstyle:ParameterNumber") @@ -157,20 +163,23 @@ public class DefaultRepositorySystemSessionFactory { @Nullable @Named("ide") WorkspaceReader workspaceRepository, SettingsDecrypter settingsDecrypter, EventSpyDispatcher eventSpyDispatcher, - MavenRepositorySystem mavenRepositorySystem, RuntimeInformation runtimeInformation) { this.artifactHandlerManager = artifactHandlerManager; this.repoSystem = repoSystem; this.workspaceRepository = workspaceRepository; this.settingsDecrypter = settingsDecrypter; this.eventSpyDispatcher = eventSpyDispatcher; - this.mavenRepositorySystem = mavenRepositorySystem; this.runtimeInformation = runtimeInformation; } + @Deprecated + public RepositorySystemSession newRepositorySession(MavenExecutionRequest request) { + return newRepositorySessionBuilder(request).build(); + } + @SuppressWarnings("checkstyle:methodLength") - public DefaultRepositorySystemSession newRepositorySession(MavenExecutionRequest request) { - DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); + public SessionBuilder newRepositorySessionBuilder(MavenExecutionRequest request) { + SessionBuilder session = MavenRepositorySystemUtils.newSession(repoSystem.createSessionBuilder()); session.setCache(request.getRepositoryCache()); Map configProps = new LinkedHashMap<>(); @@ -183,6 +192,25 @@ public class DefaultRepositorySystemSessionFactory { configProps.putAll(request.getSystemProperties()); configProps.putAll(request.getUserProperties()); + // we need to "translate" this + if (configProps.containsKey(MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY)) { + logger.warn( + "User property {} is DEPRECATED, switch to {}", + MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY, + ChainedLocalRepositoryManager.IGNORE_TAIL_AVAILABILITY); + configProps.put( + ChainedLocalRepositoryManager.IGNORE_TAIL_AVAILABILITY, + configProps.get(MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY)); + } + + // HACK: Resolver 2.0.0-alpha-2 carries a bad change: + // https://github.com/apache/maven-resolver/commit/178cfba9f3889f7e942a6a0d74716355b01a78f5 + // that is fixed in later versions by MRESOLVER-437 https://github.com/apache/maven-resolver/pull/373 + // TODO: remove this hack below once Resolver PR above is applied + if (!configProps.containsKey(ConfigurationProperties.HTTP_EXPECT_CONTINUE)) { + configProps.put(ConfigurationProperties.HTTP_EXPECT_CONTINUE, Boolean.FALSE.toString()); + } + session.setOffline(request.isOffline()); session.setChecksumPolicy(request.getGlobalChecksumPolicy()); session.setUpdatePolicy( @@ -200,6 +228,9 @@ public class DefaultRepositorySystemSessionFactory { session.setResolutionErrorPolicy( new SimpleResolutionErrorPolicy(errorPolicy, errorPolicy | ResolutionErrorPolicy.CACHE_NOT_FOUND)); + session.setArtifactDescriptorPolicy(new SimpleArtifactDescriptorPolicy( + request.isIgnoreMissingArtifactDescriptor(), request.isIgnoreInvalidArtifactDescriptor())); + session.setArtifactTypeRegistry(RepositoryUtils.newArtifactTypeRegistry(artifactHandlerManager)); session.setWorkspaceReader( @@ -336,7 +367,7 @@ public class DefaultRepositorySystemSessionFactory { // The "default" mode (user did not set anything) from now on defaults to AUTO } else if (MAVEN_RESOLVER_TRANSPORT_JDK.equals(transport)) { // Make sure (whatever extra priority is set) that resolver file/jdk is selected - configProps.put(NATIVE_FILE_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY); + configProps.put(FILE_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY); configProps.put(JDK_HTTP_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY); } else if (MAVEN_RESOLVER_TRANSPORT_APACHE.equals(transport) || MAVEN_RESOLVER_TRANSPORT_NATIVE.equals(transport)) { @@ -347,7 +378,7 @@ public class DefaultRepositorySystemSessionFactory { MAVEN_RESOLVER_TRANSPORT_APACHE); } // Make sure (whatever extra priority is set) that resolver file/apache is selected - configProps.put(NATIVE_FILE_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY); + configProps.put(FILE_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY); configProps.put(APACHE_HTTP_TRANSPORTER_PRIORITY_KEY, RESOLVER_MAX_PRIORITY); } else if (MAVEN_RESOLVER_TRANSPORT_WAGON.equals(transport)) { // Make sure (whatever extra priority is set) that wagon is selected @@ -365,52 +396,38 @@ public class DefaultRepositorySystemSessionFactory { session.setTransferListener(request.getTransferListener()); - session.setRepositoryListener(eventSpyDispatcher.chainListener(new LoggingRepositoryListener(logger))); + RepositoryListener repositoryListener = eventSpyDispatcher.chainListener(new LoggingRepositoryListener(logger)); - boolean recordReverseTree = ConfigUtils.getBoolean(session, false, MAVEN_REPO_LOCAL_RECORD_REVERSE_TREE); + boolean recordReverseTree = configProps.containsKey(MAVEN_REPO_LOCAL_RECORD_REVERSE_TREE) + && Boolean.parseBoolean((String) configProps.get(MAVEN_REPO_LOCAL_RECORD_REVERSE_TREE)); if (recordReverseTree) { - session.setRepositoryListener(new ChainedRepositoryListener( - session.getRepositoryListener(), new ReverseTreeRepositoryListener())); + repositoryListener = new ChainedRepositoryListener(repositoryListener, new ReverseTreeRepositoryListener()); } + session.setRepositoryListener(repositoryListener); - mavenRepositorySystem.injectMirror(request.getRemoteRepositories(), request.getMirrors()); - mavenRepositorySystem.injectProxy(session, request.getRemoteRepositories()); - mavenRepositorySystem.injectAuthentication(session, request.getRemoteRepositories()); + injectMirror(request.getRemoteRepositories(), request.getMirrors()); + injectProxy(proxySelector, request.getRemoteRepositories()); + injectAuthentication(authSelector, request.getRemoteRepositories()); - mavenRepositorySystem.injectMirror(request.getPluginArtifactRepositories(), request.getMirrors()); - mavenRepositorySystem.injectProxy(session, request.getPluginArtifactRepositories()); - mavenRepositorySystem.injectAuthentication(session, request.getPluginArtifactRepositories()); + injectMirror(request.getPluginArtifactRepositories(), request.getMirrors()); + injectProxy(proxySelector, request.getPluginArtifactRepositories()); + injectAuthentication(authSelector, request.getPluginArtifactRepositories()); - setUpLocalRepositoryManager(request, session); + ArrayList paths = new ArrayList<>(); + paths.add(new File(request.getLocalRepository().getBasedir())); + String localRepoTail = (String) configProps.get(MAVEN_REPO_LOCAL_TAIL); + if (localRepoTail != null) { + Arrays.stream(localRepoTail.split(",")) + .filter(p -> p != null && !p.trim().isEmpty()) + .map(File::new) + .forEach(paths::add); + } + session.withLocalRepositoryBaseDirectories(paths); return session; } - private void setUpLocalRepositoryManager(MavenExecutionRequest request, DefaultRepositorySystemSession session) { - LocalRepository localRepo = - new LocalRepository(request.getLocalRepository().getBasedir()); - - LocalRepositoryManager lrm = repoSystem.newLocalRepositoryManager(session, localRepo); - - String localRepoTail = ConfigUtils.getString(session, null, MAVEN_REPO_LOCAL_TAIL); - if (localRepoTail != null) { - boolean ignoreTailAvailability = - ConfigUtils.getBoolean(session, true, MAVEN_REPO_LOCAL_TAIL_IGNORE_AVAILABILITY); - List tail = new ArrayList<>(); - List paths = Arrays.stream(localRepoTail.split(",")) - .filter(p -> p != null && !p.trim().isEmpty()) - .collect(toList()); - for (String path : paths) { - tail.add(repoSystem.newLocalRepositoryManager(session, new LocalRepository(path))); - } - session.setLocalRepositoryManager(new ChainedLocalRepositoryManager(lrm, tail, ignoreTailAvailability)); - } else { - session.setLocalRepositoryManager(lrm); - } - } - private Map getPropertiesFromRequestedProfiles(MavenExecutionRequest request) { - HashSet activeProfileId = new HashSet<>(request.getProfileActivation().getRequiredActiveProfileIds()); activeProfileId.addAll(request.getProfileActivation().getOptionalActiveProfileIds()); @@ -428,4 +445,95 @@ public class DefaultRepositorySystemSessionFactory { return "Apache-Maven" + version + " (Java " + System.getProperty("java.version") + "; " + System.getProperty("os.name") + " " + System.getProperty("os.version") + ")"; } + + private void injectMirror(List repositories, List mirrors) { + if (repositories != null && mirrors != null) { + for (ArtifactRepository repository : repositories) { + Mirror mirror = MavenRepositorySystem.getMirror(repository, mirrors); + injectMirror(repository, mirror); + } + } + } + + private void injectMirror(ArtifactRepository repository, Mirror mirror) { + if (mirror != null) { + ArtifactRepository original = MavenRepositorySystem.createArtifactRepository( + repository.getId(), + repository.getUrl(), + repository.getLayout(), + repository.getSnapshots(), + repository.getReleases()); + + repository.setMirroredRepositories(Collections.singletonList(original)); + + repository.setId(mirror.getId()); + repository.setUrl(mirror.getUrl()); + + if (mirror.getLayout() != null && !mirror.getLayout().isEmpty()) { + repository.setLayout(original.getLayout()); + } + + repository.setBlocked(mirror.isBlocked()); + } + } + + private void injectProxy(ProxySelector selector, List repositories) { + if (repositories != null && selector != null) { + for (ArtifactRepository repository : repositories) { + repository.setProxy(getProxy(selector, repository)); + } + } + } + + private org.apache.maven.repository.Proxy getProxy(ProxySelector selector, ArtifactRepository repository) { + if (selector != null) { + RemoteRepository repo = RepositoryUtils.toRepo(repository); + org.eclipse.aether.repository.Proxy proxy = selector.getProxy(repo); + if (proxy != null) { + org.apache.maven.repository.Proxy p = new org.apache.maven.repository.Proxy(); + p.setHost(proxy.getHost()); + p.setProtocol(proxy.getType()); + p.setPort(proxy.getPort()); + if (proxy.getAuthentication() != null) { + repo = new RemoteRepository.Builder(repo).setProxy(proxy).build(); + AuthenticationContext authCtx = AuthenticationContext.forProxy(null, repo); + p.setUserName(authCtx.get(AuthenticationContext.USERNAME)); + p.setPassword(authCtx.get(AuthenticationContext.PASSWORD)); + p.setNtlmDomain(authCtx.get(AuthenticationContext.NTLM_DOMAIN)); + p.setNtlmHost(authCtx.get(AuthenticationContext.NTLM_WORKSTATION)); + authCtx.close(); + } + return p; + } + } + return null; + } + + public void injectAuthentication(AuthenticationSelector selector, List repositories) { + if (repositories != null && selector != null) { + for (ArtifactRepository repository : repositories) { + repository.setAuthentication(getAuthentication(selector, repository)); + } + } + } + + private Authentication getAuthentication(AuthenticationSelector selector, ArtifactRepository repository) { + if (selector != null) { + RemoteRepository repo = RepositoryUtils.toRepo(repository); + org.eclipse.aether.repository.Authentication auth = selector.getAuthentication(repo); + if (auth != null) { + repo = new RemoteRepository.Builder(repo) + .setAuthentication(auth) + .build(); + AuthenticationContext authCtx = AuthenticationContext.forRepository(null, repo); + Authentication result = new Authentication( + authCtx.get(AuthenticationContext.USERNAME), authCtx.get(AuthenticationContext.PASSWORD)); + result.setPrivateKey(authCtx.get(AuthenticationContext.PRIVATE_KEY_PATH)); + result.setPassphrase(authCtx.get(AuthenticationContext.PRIVATE_KEY_PASSPHRASE)); + authCtx.close(); + return result; + } + } + return null; + } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index a79aab6286..942565c9e0 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -213,8 +213,8 @@ public class DefaultSession extends AbstractSession { RepositorySystemSession repoSession = new DefaultRepositorySystemSession(session).setLocalRepositoryManager(localRepositoryManager); - MavenSession newSession = new MavenSession( - mavenSession.getContainer(), repoSession, mavenSession.getRequest(), mavenSession.getResult()); + MavenSession newSession = + new MavenSession(() -> repoSession, mavenSession.getRequest(), mavenSession.getResult()); return new DefaultSession( newSession, repositorySystem, repositories, mavenRepositorySystem, container, runtimeInformation); } diff --git a/maven-core/src/test/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactoryTest.java b/maven-core/src/test/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactoryTest.java index f21c07ae6d..748ccbb6e5 100644 --- a/maven-core/src/test/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactoryTest.java +++ b/maven-core/src/test/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactoryTest.java @@ -54,7 +54,6 @@ import static org.junit.jupiter.api.Assertions.assertThrowsExactly; */ @PlexusTest public class DefaultRepositorySystemSessionFactoryTest { - @Inject protected MavenRepositorySystem mavenRepositorySystem; @@ -81,7 +80,6 @@ public class DefaultRepositorySystemSessionFactoryTest { null, settingsDecrypter, eventSpyDispatcher, - mavenRepositorySystem, information); MavenExecutionRequest request = new DefaultMavenExecutionRequest(); @@ -104,7 +102,6 @@ public class DefaultRepositorySystemSessionFactoryTest { null, settingsDecrypter, eventSpyDispatcher, - mavenRepositorySystem, information); MavenExecutionRequest request = new DefaultMavenExecutionRequest(); @@ -139,7 +136,6 @@ public class DefaultRepositorySystemSessionFactoryTest { null, settingsDecrypter, eventSpyDispatcher, - mavenRepositorySystem, information); PlexusConfiguration plexusConfiguration = (PlexusConfiguration) systemSessionFactory @@ -182,7 +178,6 @@ public class DefaultRepositorySystemSessionFactoryTest { null, settingsDecrypter, eventSpyDispatcher, - mavenRepositorySystem, information); Map headers = (Map) systemSessionFactory @@ -219,7 +214,6 @@ public class DefaultRepositorySystemSessionFactoryTest { null, settingsDecrypter, eventSpyDispatcher, - mavenRepositorySystem, information); int connectionTimeout = (Integer) systemSessionFactory @@ -260,7 +254,6 @@ public class DefaultRepositorySystemSessionFactoryTest { null, settingsDecrypter, eventSpyDispatcher, - mavenRepositorySystem, information); int connectionTimeout = (Integer) systemSessionFactory @@ -295,7 +288,6 @@ public class DefaultRepositorySystemSessionFactoryTest { null, settingsDecrypter, eventSpyDispatcher, - mavenRepositorySystem, information); int requestTimeout = (Integer) systemSessionFactory @@ -336,7 +328,6 @@ public class DefaultRepositorySystemSessionFactoryTest { null, settingsDecrypter, eventSpyDispatcher, - mavenRepositorySystem, information); int requestTimeout = (Integer) systemSessionFactory @@ -354,7 +345,6 @@ public class DefaultRepositorySystemSessionFactoryTest { null, settingsDecrypter, eventSpyDispatcher, - mavenRepositorySystem, information); MavenExecutionRequest request = new DefaultMavenExecutionRequest(); diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java index 7117ae588e..9f17cd5f61 100644 --- a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java @@ -35,6 +35,7 @@ import org.apache.maven.api.services.SettingsBuilder; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.execution.DefaultMavenExecutionRequest; +import org.apache.maven.execution.DefaultMavenExecutionResult; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.scope.internal.MojoExecutionScope; import org.apache.maven.repository.internal.MavenRepositorySystemUtils; @@ -96,7 +97,8 @@ class TestApi { void setup() { RepositorySystemSession rss = MavenRepositorySystemUtils.newSession(); DefaultMavenExecutionRequest mer = new DefaultMavenExecutionRequest(); - MavenSession ms = new MavenSession(null, rss, mer, null); + DefaultMavenExecutionResult meres = new DefaultMavenExecutionResult(); + MavenSession ms = new MavenSession(() -> rss, mer, meres); DefaultSession session = new DefaultSession( ms, repositorySystem, diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java index 01c9b70f2a..3b04b1922b 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java @@ -117,6 +117,10 @@ public class CLIManager { public static final String COLOR = "color"; + public static final String CACHE_ARTIFACT_NOT_FOUND = "canf"; + + public static final String STRICT_ARTIFACT_DESCRIPTOR_POLICY = "sadp"; + /** This option is deprecated and may be repurposed as Java debug in a future version. * Use {@code -X/--verbose} instead. */ @Deprecated @@ -308,6 +312,17 @@ public class CLIManager { .optionalArg(true) .desc("Defines the color mode of the output. Supported are 'auto', 'always', 'never'.") .build()); + options.addOption(Option.builder(CACHE_ARTIFACT_NOT_FOUND) + .longOpt("cache-artifact-not-found") + .hasArg() + .desc( + "Defines caching behaviour for 'not found' artifacts. Supported values are 'true' (default), 'false'.") + .build()); + options.addOption(Option.builder(STRICT_ARTIFACT_DESCRIPTOR_POLICY) + .longOpt("strict-artifact-descriptor-policy") + .hasArg() + .desc("Defines 'strict' artifact descriptor policy. Supported values are 'true', 'false' (default).") + .build()); // Adding this back to make Maven fail if used options.addOption(Option.builder("llr") diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java index 2b7bc84a26..b5fdb17f99 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java @@ -1291,8 +1291,19 @@ public class MavenCli { request.setResumeFrom(commandLine.getOptionValue(CLIManager.RESUME_FROM)); enableOnPresentOption(commandLine, CLIManager.RESUME, request::setResume); request.setMakeBehavior(determineMakeBehavior(commandLine)); - request.setCacheNotFound(true); + boolean cacheNotFound = !commandLine.hasOption(CLIManager.CACHE_ARTIFACT_NOT_FOUND) + || Boolean.parseBoolean(commandLine.getOptionValue(CLIManager.CACHE_ARTIFACT_NOT_FOUND)); + request.setCacheNotFound(cacheNotFound); request.setCacheTransferError(false); + boolean strictArtifactDescriptorPolicy = commandLine.hasOption(CLIManager.STRICT_ARTIFACT_DESCRIPTOR_POLICY) + && Boolean.parseBoolean(commandLine.getOptionValue(CLIManager.STRICT_ARTIFACT_DESCRIPTOR_POLICY)); + if (strictArtifactDescriptorPolicy) { + request.setIgnoreMissingArtifactDescriptor(false); + request.setIgnoreInvalidArtifactDescriptor(false); + } else { + request.setIgnoreMissingArtifactDescriptor(true); + request.setIgnoreInvalidArtifactDescriptor(true); + } performProjectActivation(commandLine, request.getProjectActivation()); performProfileActivation(commandLine, request.getProfileActivation()); diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java index f6b86c26d6..c613513703 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java @@ -45,6 +45,7 @@ import org.codehaus.plexus.interpolation.Interpolator; import org.codehaus.plexus.interpolation.MapBasedValueSource; import org.codehaus.plexus.interpolation.StringSearchInterpolator; import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.RepositorySystemSession.CloseableSession; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.graph.DependencyFilter; import org.eclipse.aether.graph.DependencyNode; @@ -91,11 +92,14 @@ public class BootstrapCoreExtensionManager { public List loadCoreExtensions( MavenExecutionRequest request, Set providedArtifacts, List extensions) throws Exception { - RepositorySystemSession repoSession = repositorySystemSessionFactory.newRepositorySession(request); - List repositories = RepositoryUtils.toRepos(request.getPluginArtifactRepositories()); - Interpolator interpolator = createInterpolator(request); + try (CloseableSession repoSession = repositorySystemSessionFactory + .newRepositorySessionBuilder(request) + .build()) { + List repositories = RepositoryUtils.toRepos(request.getPluginArtifactRepositories()); + Interpolator interpolator = createInterpolator(request); - return resolveCoreExtensions(repoSession, repositories, providedArtifacts, extensions, interpolator); + return resolveCoreExtensions(repoSession, repositories, providedArtifacts, extensions, interpolator); + } } private List resolveCoreExtensions( diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java index dc18e206bc..e43aa5ce24 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java @@ -19,6 +19,7 @@ package org.apache.maven.repository.internal; import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystemSession.SessionBuilder; import org.eclipse.aether.artifact.DefaultArtifactType; import org.eclipse.aether.collection.DependencyGraphTransformer; import org.eclipse.aether.collection.DependencyManager; @@ -100,4 +101,51 @@ public final class MavenRepositorySystemUtils { return session; } + + /** + * Creates a new Maven-like repository system session by initializing the session with values typical for + * Maven-based resolution. In more detail, this method configures settings relevant for the processing of dependency + * graphs, most other settings remain at their generic default value. Use the various setters to further configure + * the session with authentication, mirror, proxy and other information required for your environment. + * + * @return The new repository system session, never {@code null}. + */ + public static SessionBuilder newSession(SessionBuilder session) { + DependencyTraverser depTraverser = new FatArtifactTraverser(); + session.setDependencyTraverser(depTraverser); + + DependencyManager depManager = new ClassicDependencyManager(); + session.setDependencyManager(depManager); + + DependencySelector depFilter = new AndDependencySelector( + new ScopeDependencySelector("test", "provided"), + new OptionalDependencySelector(), + new ExclusionDependencySelector()); + session.setDependencySelector(depFilter); + + DependencyGraphTransformer transformer = new ConflictResolver( + new NearestVersionSelector(), new JavaScopeSelector(), + new SimpleOptionalitySelector(), new JavaScopeDeriver()); + transformer = new ChainedDependencyGraphTransformer(transformer, new JavaDependencyContextRefiner()); + session.setDependencyGraphTransformer(transformer); + + DefaultArtifactTypeRegistry stereotypes = new DefaultArtifactTypeRegistry(); + stereotypes.add(new DefaultArtifactType("pom")); + stereotypes.add(new DefaultArtifactType("maven-plugin", "jar", "", "java")); + stereotypes.add(new DefaultArtifactType("jar", "jar", "", "java")); + stereotypes.add(new DefaultArtifactType("ejb", "jar", "", "java")); + stereotypes.add(new DefaultArtifactType("ejb-client", "jar", "client", "java")); + stereotypes.add(new DefaultArtifactType("test-jar", "jar", "tests", "java")); + stereotypes.add(new DefaultArtifactType("javadoc", "jar", "javadoc", "java")); + stereotypes.add(new DefaultArtifactType("java-source", "jar", "sources", "java", false, false)); + stereotypes.add(new DefaultArtifactType("war", "war", "", "java", false, true)); + stereotypes.add(new DefaultArtifactType("ear", "ear", "", "java", false, true)); + stereotypes.add(new DefaultArtifactType("rar", "rar", "", "java", false, true)); + stereotypes.add(new DefaultArtifactType("par", "par", "", "java", false, true)); + session.setArtifactTypeRegistry(stereotypes); + + session.setArtifactDescriptorPolicy(new SimpleArtifactDescriptorPolicy(true, true)); + + return session; + } } diff --git a/pom.xml b/pom.xml index 722d4e142c..1e17c6aedd 100644 --- a/pom.xml +++ b/pom.xml @@ -175,7 +175,7 @@ under the License. 1.26 1.0.0 4.0.1 - 2.0.0-alpha-1 + 2.0.0-alpha-2 2.0 0.9.0.M2 1.7.36