You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by cs...@apache.org on 2024/03/27 10:53:24 UTC
(maven-resolver) branch master updated: [MRESOLVER-512] ScopeManager (#445)
This is an automated email from the ASF dual-hosted git repository.
cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
The following commit(s) were added to refs/heads/master by this push:
new 39452f79 [MRESOLVER-512] ScopeManager (#445)
39452f79 is described below
commit 39452f79bf406f31309dd167121e4a86e4796c93
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Wed Mar 27 11:53:18 2024 +0100
[MRESOLVER-512] ScopeManager (#445)
In Resolver 1.x times, resolver was unaware of "resolution scope", to get the wanted resolution scope caller had to tweak and set up various nits and bits, like selectors, filters, and so on. It was easy to miss. Similarly, resolver had no "first class" type for "dependency scope" either, they were just string labels (that everyone knew HOW should behave, but was never codified) and its meaning and notion was sprinkled across several classes. Introducing new scope in these conditions [...]
The ScopeManager aims to solve these issues: it defines "resolution scope" and "dependency scope", interprets them, and allows caller to simply make a call to "resolve me main-runtime" resolution scope. No hoops and loops. Moreover, it is FASTER than Resolver 1.x was, that used always same selector (to build dirty graph), so potentially huge graph even if you needed just a bit of it, that was later chopped down to clean up the graph. ScopeManager automates selector selection/setup, an [...]
Finally, and most importantly, ScopeManager allows to be "configured": by supplying the recipe for dependency and resolution scopes, hence, makes Resolver 2.x versatile, in a sense, it is not "this or that" anymore, it can obey Maven3 and Maven4 dependency scopes at the same time.
---
https://issues.apache.org/jira/browse/MRESOLVER-512
---
.../AbstractForwardingRepositorySystemSession.java | 11 +-
.../aether/DefaultRepositorySystemSession.java | 28 +-
.../eclipse/aether/RepositorySystemSession.java | 29 +-
.../aether/artifact/ArtifactProperties.java | 4 +-
.../eclipse/aether/collection/CollectRequest.java | 23 +
.../org/eclipse/aether/scope/DependencyScope.java | 46 ++
.../org/eclipse/aether/scope/ResolutionScope.java | 34 ++
.../org/eclipse/aether/scope/ScopeManager.java | 70 +++
.../SystemDependencyScope.java} | 61 +--
.../aether/DefaultRepositorySystemSessionTest.java | 17 -
.../maven-resolver-demo-maven-plugin/pom.xml | 2 +-
.../maven-resolver-demo-snippets/pom.xml | 6 +-
.../examples/sisu/SisuRepositorySystemFactory.java | 9 +
.../org/eclipse/aether/impl/scope/BuildPath.java | 51 +++
.../org/eclipse/aether/impl/scope/BuildScope.java | 55 +++
.../aether/impl/scope/BuildScopeMatrixSource.java | 192 +++++++++
.../eclipse/aether/impl/scope/BuildScopeQuery.java | 116 +++++
.../aether/impl/scope/BuildScopeSource.java | 43 ++
.../eclipse/aether/impl/scope/CommonBuilds.java | 178 ++++++++
.../aether/impl/scope/InternalScopeManager.java | 126 ++++++
.../org/eclipse/aether/impl/scope/ProjectPath.java | 46 ++
.../impl/scope/ScopeManagerConfiguration.java | 43 ++
.../internal/impl/DefaultArtifactResolver.java | 9 +-
.../impl/collect/DependencyCollectorDelegate.java | 26 +-
.../scope/ManagedDependencyContextRefiner.java | 80 ++++
.../internal/impl/scope/ManagedScopeDeriver.java | 83 ++++
.../internal/impl/scope/ManagedScopeSelector.java | 104 +++++
.../impl/scope}/OptionalDependencySelector.java | 55 ++-
.../impl/scope/ScopeDependencySelector.java | 187 ++++++++
.../internal/impl/scope/ScopeManagerDump.java | 105 +++++
.../internal/impl/scope/ScopeManagerImpl.java | 480 +++++++++++++++++++++
.../impl/session/DefaultCloseableSession.java | 21 +-
.../impl/session/DefaultSessionBuilder.java | 12 +-
.../DependencyCollectorDelegateTestSupport.java | 13 +-
.../bf/BfWithSkipperDependencyCollectorTest.java | 2 +-
.../pom.xml | 16 +-
.../org/eclipse/aether/spi/locator/Service.java | 27 ++
.../eclipse/aether/spi/locator/ServiceLocator.java | 48 +++
.../aether/supplier/RepositorySystemSupplier.java | 37 +-
.../aether/supplier/SessionBuilderSupplier.java | 20 +-
.../supplier/RepositorySystemSupplierTest.java | 0
.../pom.xml | 10 +-
.../org/eclipse/aether/SystemScopeHandler.java | 27 ++
.../supplier/Maven4ScopeManagerConfiguration.java | 178 ++++++++
.../aether/supplier/RepositorySystemSupplier.java | 0
.../aether/supplier/SessionBuilderSupplier.java | 60 +++
.../supplier/RepositorySystemSupplierTest.java | 0
.../graph/manager/AbstractDependencyManager.java | 39 +-
.../graph/manager/ClassicDependencyManager.java | 19 +-
.../graph/manager/DefaultDependencyManager.java | 15 +-
.../graph/manager/TransitiveDependencyManager.java | 15 +-
.../graph/selector/OptionalDependencySelector.java | 3 +
.../graph/selector/ScopeDependencySelector.java | 3 +
.../util/graph/manager/DependencyManagerTest.java | 11 +-
pom.xml | 13 +-
55 files changed, 2687 insertions(+), 221 deletions(-)
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/AbstractForwardingRepositorySystemSession.java b/maven-resolver-api/src/main/java/org/eclipse/aether/AbstractForwardingRepositorySystemSession.java
index 28c8e9c1..1fd95e30 100644
--- a/maven-resolver-api/src/main/java/org/eclipse/aether/AbstractForwardingRepositorySystemSession.java
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/AbstractForwardingRepositorySystemSession.java
@@ -34,6 +34,8 @@ import org.eclipse.aether.repository.ProxySelector;
import org.eclipse.aether.repository.WorkspaceReader;
import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
import org.eclipse.aether.resolution.ResolutionErrorPolicy;
+import org.eclipse.aether.scope.ScopeManager;
+import org.eclipse.aether.scope.SystemDependencyScope;
import org.eclipse.aether.transfer.TransferListener;
/**
@@ -192,8 +194,13 @@ public abstract class AbstractForwardingRepositorySystemSession implements Repos
}
@Override
- public SystemScopeHandler getSystemScopeHandler() {
- return getSession().getSystemScopeHandler();
+ public ScopeManager getScopeManager() {
+ return getSession().getScopeManager();
+ }
+
+ @Override
+ public SystemDependencyScope getSystemDependencyScope() {
+ return getSession().getSystemDependencyScope();
}
@Override
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/DefaultRepositorySystemSession.java b/maven-resolver-api/src/main/java/org/eclipse/aether/DefaultRepositorySystemSession.java
index f64cf01d..3db5304a 100644
--- a/maven-resolver-api/src/main/java/org/eclipse/aether/DefaultRepositorySystemSession.java
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/DefaultRepositorySystemSession.java
@@ -42,6 +42,8 @@ import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.repository.WorkspaceReader;
import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
import org.eclipse.aether.resolution.ResolutionErrorPolicy;
+import org.eclipse.aether.scope.ScopeManager;
+import org.eclipse.aether.scope.SystemDependencyScope;
import org.eclipse.aether.transfer.TransferListener;
import static java.util.Objects.requireNonNull;
@@ -124,7 +126,7 @@ public final class DefaultRepositorySystemSession implements RepositorySystemSes
private RepositoryCache cache;
- private SystemScopeHandler systemScopeHandler;
+ private ScopeManager scopeManager;
private final Function<Runnable, Boolean> onSessionEndedRegistrar;
@@ -164,7 +166,6 @@ public final class DefaultRepositorySystemSession implements RepositorySystemSes
authenticationSelector = NullAuthenticationSelector.INSTANCE;
artifactTypeRegistry = NullArtifactTypeRegistry.INSTANCE;
data = new DefaultSessionData();
- systemScopeHandler = SystemScopeHandler.LEGACY;
this.onSessionEndedRegistrar = requireNonNull(onSessionEndedRegistrar, "onSessionEndedRegistrar");
}
@@ -204,7 +205,7 @@ public final class DefaultRepositorySystemSession implements RepositorySystemSes
setDependencyGraphTransformer(session.getDependencyGraphTransformer());
setData(session.getData());
setCache(session.getCache());
- setSystemScopeHandler(session.getSystemScopeHandler());
+ setScopeManager(session.getScopeManager());
this.onSessionEndedRegistrar = session::addOnSessionEndedHandler;
}
@@ -806,23 +807,32 @@ public final class DefaultRepositorySystemSession implements RepositorySystemSes
}
@Override
- public SystemScopeHandler getSystemScopeHandler() {
- return systemScopeHandler;
+ public ScopeManager getScopeManager() {
+ return scopeManager;
}
/**
- * Sets the system scope handler, must not be {@code null}.
+ * Sets the scope manager, may be {@code null}.
*
- * @param systemScopeHandler The system scope handler, cannot be {@code null}.
+ * @param scopeManager The scope manager, may be {@code null}.
* @return The session for chaining, never {@code null}.
* @since 2.0.0
*/
- public DefaultRepositorySystemSession setSystemScopeHandler(SystemScopeHandler systemScopeHandler) {
+ public DefaultRepositorySystemSession setScopeManager(ScopeManager scopeManager) {
verifyStateForMutation();
- this.systemScopeHandler = requireNonNull(systemScopeHandler);
+ this.scopeManager = scopeManager;
return this;
}
+ @Override
+ public SystemDependencyScope getSystemDependencyScope() {
+ if (scopeManager != null) {
+ return scopeManager.getSystemScope().orElse(null);
+ } else {
+ return SystemDependencyScope.LEGACY;
+ }
+ }
+
/**
* Registers onSessionEnded handler, if able to.
*
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/RepositorySystemSession.java b/maven-resolver-api/src/main/java/org/eclipse/aether/RepositorySystemSession.java
index d2abbda3..6b4ddeff 100644
--- a/maven-resolver-api/src/main/java/org/eclipse/aether/RepositorySystemSession.java
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/RepositorySystemSession.java
@@ -40,6 +40,8 @@ import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.repository.WorkspaceReader;
import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
import org.eclipse.aether.resolution.ResolutionErrorPolicy;
+import org.eclipse.aether.scope.ScopeManager;
+import org.eclipse.aether.scope.SystemDependencyScope;
import org.eclipse.aether.transfer.TransferListener;
/**
@@ -390,12 +392,12 @@ public interface RepositorySystemSession {
SessionBuilder setCache(RepositoryCache cache);
/**
- * Sets the system scope handler for session, may not be {@code null}.
+ * Sets the scope manager for session, may be {@code null}.
*
- * @param systemScopeHandler The system scope handler, may not be {@code null}.
+ * @param scopeManager The scope manager, may be {@code null}.
* @return The session for chaining, never {@code null}.
*/
- SessionBuilder setSystemScopeHandler(SystemScopeHandler systemScopeHandler);
+ SessionBuilder setScopeManager(ScopeManager scopeManager);
/**
* Adds on session ended handler to be immediately registered when this builder creates session.
@@ -752,12 +754,27 @@ public interface RepositorySystemSession {
RepositoryCache getCache();
/**
- * Returns the system scope handler, never {@code null}.
+ * Returns the scope manager to be used in this session, may be {@code null} if not set.
*
- * @return The system scope handler, never {@code null}.
+ * @return The scope manager or {@code null} if not set.
* @since 2.0.0
*/
- SystemScopeHandler getSystemScopeHandler();
+ ScopeManager getScopeManager();
+
+ /**
+ * Returns the system dependency scope.
+ * <p>
+ * Shorthand method for {@link #getScopeManager()#getSystemDependencyScope()}.
+ * <p>
+ * If {@link ScopeManager} is set, {@link #getScopeManager()} returns non-null value, the result of
+ * {@link ScopeManager#getSystemScope()} is returned (that may be {@code null}). If no {@link ScopeManager}
+ * if set, then {@link SystemDependencyScope#LEGACY} instance is returned, as lack of scope manager means that
+ * resolver operates in "legacy" mode (Maven3 compatible mode).
+ *
+ * @return The system dependency scope or {@code null} if no such scope.
+ * @since 2.0.0
+ */
+ SystemDependencyScope getSystemDependencyScope();
/**
* Registers a handler to execute when this session closed.
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/artifact/ArtifactProperties.java b/maven-resolver-api/src/main/java/org/eclipse/aether/artifact/ArtifactProperties.java
index cb67f845..595288f9 100644
--- a/maven-resolver-api/src/main/java/org/eclipse/aether/artifact/ArtifactProperties.java
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/artifact/ArtifactProperties.java
@@ -47,8 +47,8 @@ public final class ArtifactProperties {
*
* @deprecated since 2.0, the semantic carried by this property and the fact this property is coupled to Resolver
* 1.x "system" scope (that was delegated to consumer application) implies this property should not be used anymore,
- * instead, the {@link org.eclipse.aether.SystemScopeHandler} exposed via method
- * {@link RepositorySystemSession#getSystemScopeHandler()} should be used.
+ * instead, the {@link org.eclipse.aether.scope.ScopeManager} exposed via method
+ * {@link RepositorySystemSession#getScopeManager()} should be used.
*/
@Deprecated
public static final String LOCAL_PATH = "localPath";
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/collection/CollectRequest.java b/maven-resolver-api/src/main/java/org/eclipse/aether/collection/CollectRequest.java
index d524127e..1d8842e4 100644
--- a/maven-resolver-api/src/main/java/org/eclipse/aether/collection/CollectRequest.java
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/collection/CollectRequest.java
@@ -27,6 +27,7 @@ import org.eclipse.aether.RequestTrace;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.scope.ResolutionScope;
/**
* A request to collect the transitive dependencies and to build a dependency graph from them. There are three ways to
@@ -38,6 +39,7 @@ import org.eclipse.aether.repository.RemoteRepository;
* @see RepositorySystem#collectDependencies(org.eclipse.aether.RepositorySystemSession, CollectRequest)
*/
public final class CollectRequest {
+ private ResolutionScope resolutionScope;
private Artifact rootArtifact;
@@ -100,6 +102,27 @@ public final class CollectRequest {
setRepositories(repositories);
}
+ /**
+ * Gets the wanted resolution scope. If set, the {@link org.eclipse.aether.scope.ScopeManager} has to be set on
+ * session as well, otherwise it is considered user error: misconfigured collect request.
+ *
+ * @since 2.0.0
+ * @return The wanted resolution scope.
+ */
+ public ResolutionScope getResolutionScope() {
+ return resolutionScope;
+ }
+
+ /**
+ * Sets the wanted resolution scope. Usable only if {@link org.eclipse.aether.scope.ScopeManager} is used.
+ *
+ * @since 2.0.0
+ * @param resolutionScope The wanted resolution scope, may be {@code null} to "drive by yourself".
+ */
+ public void setResolutionScope(ResolutionScope resolutionScope) {
+ this.resolutionScope = resolutionScope;
+ }
+
/**
* Gets the root artifact for the dependency graph.
*
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/scope/DependencyScope.java b/maven-resolver-api/src/main/java/org/eclipse/aether/scope/DependencyScope.java
new file mode 100644
index 00000000..0dcef179
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/scope/DependencyScope.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.scope;
+
+/**
+ * Generic dependency scope.
+ *
+ * @since 2.0.0
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface DependencyScope {
+ /**
+ * The label.
+ */
+ String getId();
+
+ /**
+ * Shorthand method of {@link #getId()#equals(Object)}.
+ */
+ default boolean is(String label) {
+ return getId().equals(label);
+ }
+
+ /**
+ * Is it transitive scope?
+ */
+ boolean isTransitive();
+}
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/scope/ResolutionScope.java b/maven-resolver-api/src/main/java/org/eclipse/aether/scope/ResolutionScope.java
new file mode 100644
index 00000000..7fd0b089
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/scope/ResolutionScope.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.scope;
+
+/**
+ * Generic resolution scope.
+ *
+ * @since 2.0.0
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface ResolutionScope {
+ /**
+ * The label.
+ */
+ String getId();
+}
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/scope/ScopeManager.java b/maven-resolver-api/src/main/java/org/eclipse/aether/scope/ScopeManager.java
new file mode 100644
index 00000000..4b514745
--- /dev/null
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/scope/ScopeManager.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.scope;
+
+import java.util.Collection;
+import java.util.Optional;
+
+/**
+ * Scope manager.
+ *
+ * @since 2.0.0
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface ScopeManager {
+ /**
+ * The label.
+ */
+ String getId();
+
+ /**
+ * Returns the "system" scope, if exists.
+ * <p>
+ * This is a special scope. In this scope case, Resolver should handle it specially, as it has no POM (so is
+ * always a leaf on graph), is not in any repository, but is actually hosted on host OS file system. On resolution
+ * resolver merely checks is file present or not.
+ */
+ Optional<SystemDependencyScope> getSystemScope();
+
+ /**
+ * Returns a specific dependency scope by label.
+ * <p>
+ * Note: despite returns optional, this method may throw as well, if manager set in "strict" mode.
+ */
+ Optional<DependencyScope> getDependencyScope(String id);
+
+ /**
+ * Returns the "universe" (all) of dependency scopes.
+ */
+ Collection<DependencyScope> getDependencyScopeUniverse();
+
+ /**
+ * Returns a specific resolution scope by label.
+ * <p>
+ * Note: despite returns optional, this method may throw as well, if manager set in "strict" mode.
+ */
+ Optional<ResolutionScope> getResolutionScope(String id);
+
+ /**
+ * Returns the "universe" (all) of resolution scopes.
+ */
+ Collection<ResolutionScope> getResolutionScopeUniverse();
+}
diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/SystemScopeHandler.java b/maven-resolver-api/src/main/java/org/eclipse/aether/scope/SystemDependencyScope.java
similarity index 53%
rename from maven-resolver-api/src/main/java/org/eclipse/aether/SystemScopeHandler.java
rename to maven-resolver-api/src/main/java/org/eclipse/aether/scope/SystemDependencyScope.java
index 7199beed..1a95b98d 100644
--- a/maven-resolver-api/src/main/java/org/eclipse/aether/SystemScopeHandler.java
+++ b/maven-resolver-api/src/main/java/org/eclipse/aether/scope/SystemDependencyScope.java
@@ -16,50 +16,26 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.eclipse.aether;
+package org.eclipse.aether.scope;
import java.util.Map;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.ArtifactProperties;
-import org.eclipse.aether.graph.Dependency;
-import org.eclipse.aether.graph.DependencyNode;
/**
- * In Resolver 1.x line, the "system" scope represented special artifacts. In 2.x resolver testing for this scope
- * is now delegated to consumer application. Class or component that wants to test for this special dependency scope
- * should use this interface, with implementation provided by consumer application.
+ * A special dependency scope: "system".
* <p>
- * System is a special scope that tells resolver that dependency is not to be found in any regular repository, so it
- * should not even try to resolve the artifact from them. Dependency in this scope does not have artifact descriptor
- * either. Artifacts in this scope should have the "local path" property set, pointing to a file on local system, where
- * the backing file should reside. Resolution of artifacts in this scope fails, if backing file does not exist
- * (no property set, or property contains invalid path, or the path points to a non-existent file).
+ * This is a special scope. In this scope case, Resolver should handle dependencies specially, as they have no POM (so
+ * are always a leaf on graph), are not in any repository, but are actually hosted on host OS file system. On resolution
+ * resolver merely checks is file present or not.
*
* @since 2.0.0
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
*/
-public interface SystemScopeHandler {
- /**
- * Returns {@code true} only, if passed in scope label represents "system" scope (as consumer project defines it).
- */
- boolean isSystemScope(String scope);
-
- /**
- * Returns {@code true} if given dependency is in "system" scope.
- */
- default boolean isSystemScope(Dependency dependency) {
- return dependency != null && isSystemScope(dependency.getScope());
- }
-
- /**
- * Returns {@code true} if given dependency node dependency is in "system" scope.
- */
- default boolean isSystemScope(DependencyNode dependencyNode) {
- return dependencyNode != null
- && dependencyNode.getDependency() != null
- && isSystemScope(dependencyNode.getDependency());
- }
-
+public interface SystemDependencyScope extends DependencyScope {
/**
* Returns system path string of provided artifact, or {@code null}.
*
@@ -78,14 +54,9 @@ public interface SystemScopeHandler {
void setSystemPath(Map<String, String> properties, String systemPath);
/**
- * The equivalent of Resolver 1.x "system" scope.
+ * The "legacy" system scope, used when there is no {@link ScopeManager} set on session.
*/
- SystemScopeHandler LEGACY = new SystemScopeHandler() {
- @Override
- public boolean isSystemScope(String scope) {
- return "system".equals(scope);
- }
-
+ SystemDependencyScope LEGACY = new SystemDependencyScope() {
@Override
public String getSystemPath(Artifact artifact) {
return artifact.getProperty(ArtifactProperties.LOCAL_PATH, null);
@@ -99,5 +70,15 @@ public interface SystemScopeHandler {
properties.put(ArtifactProperties.LOCAL_PATH, systemPath);
}
}
+
+ @Override
+ public String getId() {
+ return "system";
+ }
+
+ @Override
+ public boolean isTransitive() {
+ return false;
+ }
};
}
diff --git a/maven-resolver-api/src/test/java/org/eclipse/aether/DefaultRepositorySystemSessionTest.java b/maven-resolver-api/src/test/java/org/eclipse/aether/DefaultRepositorySystemSessionTest.java
index 85bbf57b..a9d16f27 100644
--- a/maven-resolver-api/src/test/java/org/eclipse/aether/DefaultRepositorySystemSessionTest.java
+++ b/maven-resolver-api/src/test/java/org/eclipse/aether/DefaultRepositorySystemSessionTest.java
@@ -18,7 +18,6 @@
*/
package org.eclipse.aether;
-import java.lang.reflect.Method;
import java.util.Map;
import org.eclipse.aether.repository.Authentication;
@@ -27,7 +26,6 @@ import org.eclipse.aether.repository.AuthenticationDigest;
import org.eclipse.aether.repository.Proxy;
import org.eclipse.aether.repository.RemoteRepository;
import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
import static org.junit.jupiter.api.Assertions.*;
@@ -109,19 +107,4 @@ public class DefaultRepositorySystemSessionTest {
// expected
}
}
-
- @Test
- void testCopyRepositorySystemSession() throws Exception {
- RepositorySystemSession session = Mockito.mock(RepositorySystemSession.class, Mockito.RETURNS_MOCKS);
-
- RepositorySystemSession newSession = new DefaultRepositorySystemSession(session);
-
- Method[] methods = RepositorySystemSession.class.getMethods();
-
- for (Method method : methods) {
- if (method.getParameterCount() == 0) {
- assertEquals(method.invoke(session) == null, method.invoke(newSession) == null, method.getName());
- }
- }
- }
}
diff --git a/maven-resolver-demos/maven-resolver-demo-maven-plugin/pom.xml b/maven-resolver-demos/maven-resolver-demo-maven-plugin/pom.xml
index 620acbab..6c113d51 100644
--- a/maven-resolver-demos/maven-resolver-demo-maven-plugin/pom.xml
+++ b/maven-resolver-demos/maven-resolver-demo-maven-plugin/pom.xml
@@ -40,7 +40,7 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
- <version>${mavenVersion}</version>
+ <version>${maven3Version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
diff --git a/maven-resolver-demos/maven-resolver-demo-snippets/pom.xml b/maven-resolver-demos/maven-resolver-demo-snippets/pom.xml
index 20031b9c..1ee333b5 100644
--- a/maven-resolver-demos/maven-resolver-demo-snippets/pom.xml
+++ b/maven-resolver-demos/maven-resolver-demo-snippets/pom.xml
@@ -81,17 +81,17 @@
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
- <artifactId>maven-resolver-supplier</artifactId>
+ <artifactId>maven-resolver-supplier-mvn3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
- <version>${mavenVersion}</version>
+ <version>${maven3Version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model-builder</artifactId>
- <version>${mavenVersion}</version>
+ <version>${maven3Version}</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
diff --git a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/sisu/SisuRepositorySystemFactory.java b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/sisu/SisuRepositorySystemFactory.java
index 9e267b4f..7d927c19 100644
--- a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/sisu/SisuRepositorySystemFactory.java
+++ b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/sisu/SisuRepositorySystemFactory.java
@@ -27,6 +27,8 @@ import com.google.inject.Module;
import org.apache.maven.model.building.DefaultModelBuilderFactory;
import org.apache.maven.model.building.ModelBuilder;
import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.util.version.GenericVersionScheme;
+import org.eclipse.aether.version.VersionScheme;
import org.eclipse.sisu.launch.Main;
import org.eclipse.sisu.space.BeanScanning;
@@ -49,4 +51,11 @@ public class SisuRepositorySystemFactory {
return new DefaultModelBuilderFactory().newInstance();
}
}
+
+ @Named
+ private static class VersionSchemeProvider implements Provider<VersionScheme> {
+ public VersionScheme get() {
+ return new GenericVersionScheme();
+ }
+ }
}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildPath.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildPath.java
new file mode 100644
index 00000000..f0fa594d
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildPath.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.impl.scope;
+
+/**
+ * Label for "build path", like "compile", "runtime", etc.
+ *
+ * @since 2.0.0
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface BuildPath {
+ /**
+ * The label.
+ */
+ String getId();
+
+ /**
+ * A flag denoting that this build path "reverses" the expected order of project paths.
+ * <p>
+ * For example: "compile" step expects "main" then "test" order (compile them in this order).
+ * On the other hand, "runtime" expects "test" to have run first. In this sense, "runtime" is reverse.
+ * <p>
+ * If {@code false}, then {@link ProjectPath#order()} is used to sort project paths, otherwise the
+ * {@link ProjectPath#reverseOrder()} is used to sort them.
+ */
+ boolean isReverse();
+
+ /**
+ * Returns the "order" of this path, usable to sort against other instances.
+ * Expected natural order is "compile", "runtime"... (basically like the processing order).
+ */
+ int order();
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildScope.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildScope.java
new file mode 100644
index 00000000..6ea10f95
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildScope.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.impl.scope;
+
+import java.util.Set;
+
+/**
+ * Build scope is certain combination of {@link ProjectPath} and {@link BuildPath}.
+ *
+ * @since 2.0.0
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface BuildScope {
+ /**
+ * The label.
+ */
+ String getId();
+
+ /**
+ * The project paths this scope belongs to.
+ */
+ Set<ProjectPath> getProjectPaths();
+
+ /**
+ * The build paths this scope belongs to.
+ */
+ Set<BuildPath> getBuildPaths();
+
+ /**
+ * Returns the "order" of this scope, usable to sort against other instances.
+ * Expected natural order is "main-compile", "test-compile"... (basically like the processing order).
+ * <p>
+ * Note: this order is unrelated to {@link ProjectPath#order()} and {@link BuildPath#order()} and
+ * should be used only to sort build scope instances.
+ */
+ int order();
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildScopeMatrixSource.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildScopeMatrixSource.java
new file mode 100644
index 00000000..31dc8004
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildScopeMatrixSource.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.impl.scope;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Generic matrix generator for {@link ProjectPath} and {@link BuildPath} combinations (all of them).
+ *
+ * @since 2.0.0
+ */
+public final class BuildScopeMatrixSource implements BuildScopeSource {
+ private final Set<ProjectPath> projectPaths;
+ private final Set<BuildPath> buildPaths;
+ private final Map<String, BuildScope> buildScopes;
+
+ public BuildScopeMatrixSource(
+ Collection<ProjectPath> projectPaths, Collection<BuildPath> buildPaths, BuildScope... extras) {
+ requireNonNull(projectPaths, "projectPath");
+ requireNonNull(buildPaths, "buildPaths");
+ if (projectPaths.isEmpty() || buildPaths.isEmpty()) {
+ throw new IllegalArgumentException("empty matrix");
+ }
+ HashMap<String, BuildScope> buildScopes = new HashMap<>();
+ AtomicInteger counter = new AtomicInteger(0);
+ buildPaths.stream().sorted(Comparator.comparing(BuildPath::order)).forEach(buildPath -> {
+ Stream<ProjectPath> projectPathStream;
+ if (buildPath.isReverse()) {
+ projectPathStream = projectPaths.stream().sorted(Comparator.comparing(ProjectPath::reverseOrder));
+ } else {
+ projectPathStream = projectPaths.stream().sorted(Comparator.comparing(ProjectPath::order));
+ }
+ projectPathStream.forEach(projectPath -> {
+ String id = createId(projectPath, buildPath);
+ buildScopes.put(
+ id,
+ new BuildScopeImpl(
+ id,
+ Collections.singleton(projectPath),
+ Collections.singleton(buildPath),
+ counter.incrementAndGet()));
+ });
+ });
+ for (BuildScope extra : extras) {
+ buildScopes.put(extra.getId(), extra);
+ }
+ this.buildScopes = Collections.unmodifiableMap(buildScopes);
+
+ // now collect all paths
+ HashSet<ProjectPath> pp = new HashSet<>(projectPaths);
+ HashSet<BuildPath> bp = new HashSet<>(buildPaths);
+ buildScopes.values().forEach(s -> {
+ pp.addAll(s.getProjectPaths());
+ bp.addAll(s.getBuildPaths());
+ });
+ this.projectPaths = Collections.unmodifiableSet(pp);
+ this.buildPaths = Collections.unmodifiableSet(bp);
+ }
+
+ private String createId(ProjectPath projectPath, BuildPath buildPath) {
+ return projectPath.getId() + "-" + buildPath.getId();
+ }
+
+ @Override
+ public Collection<BuildScope> query(Collection<BuildScopeQuery> queries) {
+ HashSet<BuildScope> result = new HashSet<>();
+ for (BuildScopeQuery query : queries) {
+ switch (query.getMode()) {
+ case ALL:
+ result.addAll(all());
+ break; // we added all, whatever is after this, is unimportant
+ case BY_PROJECT_PATH:
+ result.addAll(byProjectPath(query.getProjectPath()));
+ continue;
+ case BY_BUILD_PATH:
+ result.addAll(byBuildPath(query.getBuildPath()));
+ continue;
+ case SELECT:
+ result.addAll(select(query.getProjectPath(), query.getBuildPath()));
+ continue;
+ case SINGLETON:
+ result.addAll(singleton(query.getProjectPath(), query.getBuildPath()));
+ continue;
+ default:
+ throw new IllegalArgumentException("Unsupported query");
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Collection<ProjectPath> allProjectPaths() {
+ return projectPaths;
+ }
+
+ @Override
+ public Collection<BuildPath> allBuildPaths() {
+ return buildPaths;
+ }
+
+ private Collection<BuildScope> all() {
+ return buildScopes.values();
+ }
+
+ private Collection<BuildScope> byProjectPath(ProjectPath projectPath) {
+ return all().stream()
+ .filter(s -> s.getProjectPaths().contains(projectPath))
+ .collect(Collectors.toSet());
+ }
+
+ private Collection<BuildScope> byBuildPath(BuildPath buildPath) {
+ return all().stream().filter(s -> s.getBuildPaths().contains(buildPath)).collect(Collectors.toSet());
+ }
+
+ private Collection<BuildScope> singleton(ProjectPath projectPath, BuildPath buildPath) {
+ BuildScope result = buildScopes.get(createId(projectPath, buildPath));
+ if (result == null) {
+ throw new IllegalArgumentException("no such build scope");
+ }
+ return Collections.singleton(result);
+ }
+
+ private Collection<BuildScope> select(ProjectPath projectPath, BuildPath buildPath) {
+ HashSet<BuildScope> result = new HashSet<>();
+ buildScopes.values().stream()
+ .filter(s -> s.getProjectPaths().contains(projectPath)
+ && s.getBuildPaths().contains(buildPath))
+ .forEach(result::add);
+ return result;
+ }
+
+ private static final class BuildScopeImpl implements BuildScope {
+ private final String id;
+ private final Set<ProjectPath> projectPaths;
+ private final Set<BuildPath> buildPaths;
+ private final int order;
+
+ private BuildScopeImpl(String id, Set<ProjectPath> projectPaths, Set<BuildPath> buildPaths, int order) {
+ this.id = id;
+ this.projectPaths = projectPaths;
+ this.buildPaths = buildPaths;
+ this.order = order;
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public Set<ProjectPath> getProjectPaths() {
+ return projectPaths;
+ }
+
+ @Override
+ public Set<BuildPath> getBuildPaths() {
+ return buildPaths;
+ }
+
+ @Override
+ public int order() {
+ return order;
+ }
+ }
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildScopeQuery.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildScopeQuery.java
new file mode 100644
index 00000000..5fd66532
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildScopeQuery.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.impl.scope;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Build scope query.
+ *
+ * @since 2.0.0
+ */
+public final class BuildScopeQuery {
+ public enum Mode {
+ ALL,
+ BY_PROJECT_PATH,
+ BY_BUILD_PATH,
+ SELECT,
+ SINGLETON;
+
+ private void validate(ProjectPath projectPath, BuildPath buildPath) {
+ if ((this == ALL) && (projectPath != null || buildPath != null)) {
+ throw new IllegalArgumentException(this.name() + " requires no parameter");
+ } else if (this == BY_PROJECT_PATH && (projectPath == null || buildPath != null)) {
+ throw new IllegalArgumentException(this.name() + " requires project path parameter only");
+ } else if (this == BY_BUILD_PATH && (projectPath != null || buildPath == null)) {
+ throw new IllegalArgumentException(this.name() + " requires build path parameter only");
+ } else if ((this == SELECT || this == SINGLETON) && (projectPath == null || buildPath == null)) {
+ throw new IllegalArgumentException(this.name() + " requires both parameters");
+ }
+ }
+ }
+
+ private final Mode mode;
+ private final ProjectPath projectPath;
+ private final BuildPath buildPath;
+
+ private BuildScopeQuery(Mode mode, ProjectPath projectPath, BuildPath buildPath) {
+ this.mode = requireNonNull(mode, "mode");
+ mode.validate(projectPath, buildPath);
+ this.projectPath = projectPath;
+ this.buildPath = buildPath;
+ }
+
+ public Mode getMode() {
+ return mode;
+ }
+
+ public ProjectPath getProjectPath() {
+ return projectPath;
+ }
+
+ public BuildPath getBuildPath() {
+ return buildPath;
+ }
+
+ @Override
+ public String toString() {
+ if ((mode == Mode.ALL)) {
+ return mode.name();
+ } else if (mode == Mode.BY_PROJECT_PATH) {
+ return mode.name() + "(" + projectPath.getId() + ")";
+ } else if (mode == Mode.BY_BUILD_PATH) {
+ return mode.name() + "(" + buildPath.getId() + ")";
+ } else {
+ return mode.name() + "(" + projectPath.getId() + ", " + buildPath.getId() + ")";
+ }
+ }
+
+ public static Collection<BuildScopeQuery> all() {
+ return Collections.singleton(new BuildScopeQuery(Mode.ALL, null, null));
+ }
+
+ public static Collection<BuildScopeQuery> byProjectPath(ProjectPath projectPath) {
+ return Collections.singleton(new BuildScopeQuery(Mode.BY_PROJECT_PATH, projectPath, null));
+ }
+
+ public static Collection<BuildScopeQuery> byBuildPath(BuildPath buildPath) {
+ return Collections.singleton(new BuildScopeQuery(Mode.BY_BUILD_PATH, null, buildPath));
+ }
+
+ public static Collection<BuildScopeQuery> select(ProjectPath projectPath, BuildPath buildPath) {
+ return Collections.singleton(new BuildScopeQuery(Mode.SELECT, projectPath, buildPath));
+ }
+
+ public static Collection<BuildScopeQuery> singleton(ProjectPath projectPath, BuildPath buildPath) {
+ return Collections.singleton(new BuildScopeQuery(Mode.SINGLETON, projectPath, buildPath));
+ }
+
+ @SafeVarargs
+ public static Collection<BuildScopeQuery> union(Collection<BuildScopeQuery>... buildScopeQueries) {
+ HashSet<BuildScopeQuery> result = new HashSet<>();
+ Arrays.asList(buildScopeQueries).forEach(result::addAll);
+ return result;
+ }
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildScopeSource.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildScopeSource.java
new file mode 100644
index 00000000..6a3bb32b
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/BuildScopeSource.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.impl.scope;
+
+import java.util.Collection;
+
+/**
+ * Build scope source.
+ *
+ * @since 2.0.0
+ */
+public interface BuildScopeSource {
+ /**
+ * Returns all project paths this source has.
+ */
+ Collection<ProjectPath> allProjectPaths();
+
+ /**
+ * Returns all build paths this source has.
+ */
+ Collection<BuildPath> allBuildPaths();
+
+ /**
+ * Processes all queries and returns all build scopes that query selected.
+ */
+ Collection<BuildScope> query(Collection<BuildScopeQuery> queries);
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/CommonBuilds.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/CommonBuilds.java
new file mode 100644
index 00000000..6aed19fe
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/CommonBuilds.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.impl.scope;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Set of constants meant to be used in "common builds".
+ *
+ * @since 2.0.0
+ */
+public final class CommonBuilds {
+ private CommonBuilds() {}
+
+ private abstract static class Label {
+ private final String id;
+
+ protected Label(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Label label = (Label) o;
+ return Objects.equals(id, label.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+
+ @Override
+ public String toString() {
+ return id;
+ }
+ }
+
+ private static final class ProjectPathImpl extends Label implements ProjectPath {
+ private final int order;
+ private final int reverseOrder;
+
+ private ProjectPathImpl(String id, int order, int reverseOrder) {
+ super(id);
+ this.order = order;
+ this.reverseOrder = reverseOrder;
+ }
+
+ @Override
+ public int order() {
+ return order;
+ }
+
+ @Override
+ public int reverseOrder() {
+ return reverseOrder;
+ }
+ }
+
+ private static final class BuildPathImpl extends Label implements BuildPath {
+ private final boolean reverse;
+ private final int order;
+
+ private BuildPathImpl(String id, boolean reverse, int order) {
+ super(id);
+ this.reverse = reverse;
+ this.order = order;
+ }
+
+ @Override
+ public boolean isReverse() {
+ return reverse;
+ }
+
+ @Override
+ public int order() {
+ return order;
+ }
+ }
+
+ private static final class BuildScopeImpl extends Label implements BuildScope {
+ private final Set<ProjectPath> projectPaths;
+ private final Set<BuildPath> buildPaths;
+ private final int order;
+
+ private BuildScopeImpl(String id, Set<ProjectPath> projectPaths, Set<BuildPath> buildPaths, int order) {
+ super(id);
+ this.projectPaths = projectPaths;
+ this.buildPaths = buildPaths;
+ this.order = order;
+ }
+
+ @Override
+ public Set<ProjectPath> getProjectPaths() {
+ return projectPaths;
+ }
+
+ @Override
+ public Set<BuildPath> getBuildPaths() {
+ return buildPaths;
+ }
+
+ @Override
+ public int order() {
+ return order;
+ }
+ }
+
+ /**
+ * A common "main" project path.
+ */
+ public static final ProjectPath PROJECT_PATH_MAIN = new ProjectPathImpl("main", 1, 3);
+
+ /**
+ * A common "test" project path.
+ */
+ public static final ProjectPath PROJECT_PATH_TEST = new ProjectPathImpl("test", 2, 1);
+
+ /**
+ * A common "it" project path.
+ */
+ public static final ProjectPath PROJECT_PATH_IT = new ProjectPathImpl("it", 3, 2);
+
+ /**
+ * A common "preprocess" build path.
+ */
+ public static final BuildPath BUILD_PATH_PREPROCESS = new BuildPathImpl("preprocess", false, 1);
+
+ /**
+ * A common "compile" build path.
+ */
+ public static final BuildPath BUILD_PATH_COMPILE = new BuildPathImpl("compile", false, 2);
+
+ /**
+ * A common "runtime" build path.
+ */
+ public static final BuildPath BUILD_PATH_RUNTIME = new BuildPathImpl("runtime", true, 3);
+
+ /**
+ * Maven2/Maven3 special build scope: it did not distinguish between "test compile"
+ * and "test runtime", but lumped both together into "test".
+ */
+ public static final BuildScope MAVEN_TEST_BUILD_SCOPE = new BuildScopeImpl(
+ "test",
+ Collections.singleton(PROJECT_PATH_TEST),
+ Collections.unmodifiableSet(new HashSet<>(Arrays.asList(BUILD_PATH_COMPILE, BUILD_PATH_RUNTIME))),
+ 10);
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/InternalScopeManager.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/InternalScopeManager.java
new file mode 100644
index 00000000..ac3643f7
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/InternalScopeManager.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.impl.scope;
+
+import java.util.Collection;
+import java.util.Optional;
+
+import org.eclipse.aether.collection.CollectResult;
+import org.eclipse.aether.collection.DependencyGraphTransformer;
+import org.eclipse.aether.collection.DependencySelector;
+import org.eclipse.aether.graph.DependencyFilter;
+import org.eclipse.aether.scope.DependencyScope;
+import org.eclipse.aether.scope.ResolutionScope;
+import org.eclipse.aether.scope.ScopeManager;
+import org.eclipse.aether.scope.SystemDependencyScope;
+
+/**
+ * Internal scope manager.
+ *
+ * @since 2.0.0
+ */
+public interface InternalScopeManager extends ScopeManager {
+ /**
+ * The "width" of scope: is basically sum of all distinct {@link ProjectPath} and {@link BuildPath} that are
+ * in build scopes the scope is present in. The more of them, the "wider" is the scope. Transitive scopes are
+ * weighted more as well.
+ * <p>
+ * The {@link ProjectPath#order()} makes given path "weigh" more. So a scope being present only in
+ * "main" project path is wider than scope being present only in "test" project path.
+ * <p>
+ * Interpretation: the bigger the returned integer is, the "wider" the scope is. The numbers should not serve
+ * any other purposes, merely to sort scope instances by "width" (i.e. from "widest" to "narrowest").
+ */
+ int getDependencyScopeWidth(DependencyScope dependencyScope);
+
+ /**
+ * Returns the {@link BuildScope} that this scope deem as main.
+ */
+ Optional<BuildScope> getDependencyScopeMainProjectBuildScope(DependencyScope dependencyScope);
+
+ /**
+ * Resolver specific: dependency selector to be used to support this scope (with its dependency
+ * and resolution scopes).
+ */
+ DependencySelector getDependencySelector(ResolutionScope resolutionScope);
+
+ /**
+ * Resolver specific: dependency graph transformer to be used to support this scope (with its dependency
+ * and resolution scopes).
+ */
+ DependencyGraphTransformer getDependencyGraphTransformer(ResolutionScope resolutionScope);
+
+ /**
+ * Resolver specific: post-processing to be used to support this scope (with its dependency
+ * and resolution scopes).
+ */
+ CollectResult postProcess(ResolutionScope resolutionScope, CollectResult collectResult);
+
+ /**
+ * Resolver specific: dependency filter to be used to support this scope (with its dependency
+ * and resolution scopes).
+ */
+ DependencyFilter getDependencyFilter(ResolutionScope resolutionScope);
+
+ /**
+ * The mode of resolution scope: eliminate (remove all occurrences) or just remove.
+ */
+ enum Mode {
+ /**
+ * Mode where artifacts in non-wanted scopes are completely eliminated. In other words, this mode ensures
+ * that if a dependency was removed due unwanted scope, it is guaranteed that no such dependency will appear
+ * anywhere else in the resulting graph either.
+ */
+ ELIMINATE,
+
+ /**
+ * Mode where artifacts in non-wanted scopes are removed only. In other words, they will NOT prevent (as in
+ * they will not "dominate") other possibly appearing occurrences of same artifact in the graph.
+ */
+ REMOVE
+ }
+
+ /**
+ * Creates dependency scope instance.
+ * <p>
+ * Should be invoked only via {@link ScopeManagerConfiguration#buildDependencyScopes(InternalScopeManager)}.
+ */
+ DependencyScope createDependencyScope(String id, boolean transitive, Collection<BuildScopeQuery> presence);
+
+ /**
+ * Creates system dependency scope instance. This method may be invoked only once, as there can be only one
+ * instance of {@link SystemDependencyScope}!
+ * <p>
+ * Should be invoked only via {@link ScopeManagerConfiguration#buildDependencyScopes(InternalScopeManager)}.
+ */
+ SystemDependencyScope createSystemDependencyScope(
+ String id, boolean transitive, Collection<BuildScopeQuery> presence, String systemPathProperty);
+
+ /**
+ * Creates resolution scope instance.
+ * <p>
+ * Should be invoked only via {@link ScopeManagerConfiguration#buildResolutionScopes(InternalScopeManager)}.
+ */
+ ResolutionScope createResolutionScope(
+ String id,
+ Mode mode,
+ Collection<BuildScopeQuery> wantedPresence,
+ Collection<DependencyScope> explicitlyIncluded,
+ Collection<DependencyScope> transitivelyExcluded);
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/ProjectPath.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/ProjectPath.java
new file mode 100644
index 00000000..ae8a70b3
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/ProjectPath.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.impl.scope;
+
+/**
+ * Label for "project path", like "main", "test", but could be "it", etc.
+ *
+ * @since 2.0.0
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface ProjectPath {
+ /**
+ * The label.
+ */
+ String getId();
+
+ /**
+ * Returns the "order" of this path, usable to sort against other instances.
+ * Expected natural order is "main", "test"... (basically like the processing order).
+ */
+ int order();
+
+ /**
+ * Returns the "reverse order" of this path, usable to sort against other instances.
+ * Expected natural order is "test", "main"... (basically like the processing order).
+ */
+ int reverseOrder();
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/ScopeManagerConfiguration.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/ScopeManagerConfiguration.java
new file mode 100644
index 00000000..1794d62e
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/scope/ScopeManagerConfiguration.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.impl.scope;
+
+import java.util.Collection;
+
+import org.eclipse.aether.scope.DependencyScope;
+import org.eclipse.aether.scope.ResolutionScope;
+
+/**
+ * Scope manager configuration.
+ *
+ * @since 2.0.0
+ */
+public interface ScopeManagerConfiguration {
+ String getId();
+
+ boolean isStrictDependencyScopes();
+
+ boolean isStrictResolutionScopes();
+
+ BuildScopeSource getBuildScopeSource();
+
+ Collection<DependencyScope> buildDependencyScopes(InternalScopeManager internalScopeManager);
+
+ Collection<ResolutionScope> buildResolutionScopes(InternalScopeManager internalScopeManager);
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultArtifactResolver.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultArtifactResolver.java
index ca27ab8e..15e10145 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultArtifactResolver.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultArtifactResolver.java
@@ -59,6 +59,7 @@ import org.eclipse.aether.resolution.ResolutionErrorPolicy;
import org.eclipse.aether.resolution.VersionRequest;
import org.eclipse.aether.resolution.VersionResolutionException;
import org.eclipse.aether.resolution.VersionResult;
+import org.eclipse.aether.scope.SystemDependencyScope;
import org.eclipse.aether.spi.connector.ArtifactDownload;
import org.eclipse.aether.spi.connector.RepositoryConnector;
import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilter;
@@ -181,8 +182,10 @@ public class DefaultArtifactResolver implements ArtifactResolver {
try (SyncContext shared = syncContextFactory.newInstance(session, true);
SyncContext exclusive = syncContextFactory.newInstance(session, false)) {
Collection<Artifact> artifacts = new ArrayList<>(requests.size());
+ SystemDependencyScope systemDependencyScope = session.getSystemDependencyScope();
for (ArtifactRequest request : requests) {
- if (session.getSystemScopeHandler().getSystemPath(request.getArtifact()) != null) {
+ if (systemDependencyScope != null
+ && systemDependencyScope.getSystemPath(request.getArtifact()) != null) {
continue;
}
artifacts.add(request.getArtifact());
@@ -200,6 +203,7 @@ public class DefaultArtifactResolver implements ArtifactResolver {
RepositorySystemSession session,
Collection<? extends ArtifactRequest> requests)
throws ArtifactResolutionException {
+ SystemDependencyScope systemDependencyScope = session.getSystemDependencyScope();
SyncContext current = shared;
try {
while (true) {
@@ -227,7 +231,8 @@ public class DefaultArtifactResolver implements ArtifactResolver {
artifactResolving(session, trace, artifact);
}
- String localPath = session.getSystemScopeHandler().getSystemPath(artifact);
+ String localPath =
+ systemDependencyScope != null ? systemDependencyScope.getSystemPath(artifact) : null;
if (localPath != null) {
// unhosted artifact, just validate file
Path path = Paths.get(localPath);
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyCollectorDelegate.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyCollectorDelegate.java
index 80c41b96..d7b5cd9c 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyCollectorDelegate.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyCollectorDelegate.java
@@ -44,6 +44,7 @@ import org.eclipse.aether.impl.ArtifactDescriptorReader;
import org.eclipse.aether.impl.DependencyCollector;
import org.eclipse.aether.impl.RemoteRepositoryManager;
import org.eclipse.aether.impl.VersionRangeResolver;
+import org.eclipse.aether.impl.scope.InternalScopeManager;
import org.eclipse.aether.repository.ArtifactRepository;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactDescriptorException;
@@ -52,6 +53,8 @@ import org.eclipse.aether.resolution.ArtifactDescriptorResult;
import org.eclipse.aether.resolution.VersionRangeRequest;
import org.eclipse.aether.resolution.VersionRangeResolutionException;
import org.eclipse.aether.resolution.VersionRangeResult;
+import org.eclipse.aether.scope.ResolutionScope;
+import org.eclipse.aether.scope.SystemDependencyScope;
import org.eclipse.aether.util.ConfigUtils;
import org.eclipse.aether.util.graph.transformer.TransformationContextKeys;
import org.eclipse.aether.version.Version;
@@ -114,7 +117,9 @@ public abstract class DependencyCollectorDelegate implements DependencyCollector
throws DependencyCollectionException {
requireNonNull(session, "session cannot be null");
requireNonNull(request, "request cannot be null");
- session = optimizeSession(session);
+
+ InternalScopeManager scopeManager = (InternalScopeManager) session.getScopeManager();
+ session = setUpSession(session, request, scopeManager);
RequestTrace trace = RequestTrace.newChild(request.getTrace(), request);
@@ -246,7 +251,11 @@ public abstract class DependencyCollectorDelegate implements DependencyCollector
throw new DependencyCollectionException(result);
}
- return result;
+ if (request.getResolutionScope() != null) {
+ return scopeManager.postProcess(request.getResolutionScope(), result);
+ } else {
+ return result;
+ }
}
/**
@@ -283,9 +292,17 @@ public abstract class DependencyCollectorDelegate implements DependencyCollector
Results results)
throws DependencyCollectionException;
- protected RepositorySystemSession optimizeSession(RepositorySystemSession session) {
+ protected RepositorySystemSession setUpSession(
+ RepositorySystemSession session, CollectRequest collectRequest, InternalScopeManager scopeManager) {
DefaultRepositorySystemSession optimized = new DefaultRepositorySystemSession(session);
optimized.setArtifactTypeRegistry(CachingArtifactTypeRegistry.newInstance(session));
+
+ ResolutionScope resolutionScope = collectRequest.getResolutionScope();
+ if (resolutionScope != null) {
+ requireNonNull(scopeManager, "ScopeManager is not set on session");
+ optimized.setDependencySelector(scopeManager.getDependencySelector(resolutionScope));
+ optimized.setDependencyGraphTransformer(scopeManager.getDependencyGraphTransformer(resolutionScope));
+ }
return optimized;
}
@@ -394,7 +411,8 @@ public abstract class DependencyCollectorDelegate implements DependencyCollector
}
protected static boolean isLackingDescriptor(RepositorySystemSession session, Artifact artifact) {
- return session.getSystemScopeHandler().getSystemPath(artifact) != null;
+ SystemDependencyScope systemDependencyScope = session.getSystemDependencyScope();
+ return systemDependencyScope != null && systemDependencyScope.getSystemPath(artifact) != null;
}
protected static List<RemoteRepository> getRemoteRepositories(
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ManagedDependencyContextRefiner.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ManagedDependencyContextRefiner.java
new file mode 100644
index 00000000..c947f233
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ManagedDependencyContextRefiner.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.internal.impl.scope;
+
+import org.eclipse.aether.collection.DependencyGraphTransformationContext;
+import org.eclipse.aether.collection.DependencyGraphTransformer;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.graph.DependencyNode;
+import org.eclipse.aether.impl.scope.BuildScope;
+import org.eclipse.aether.impl.scope.InternalScopeManager;
+import org.eclipse.aether.scope.DependencyScope;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A dependency graph transformer that refines the request context for nodes that belong to the "project" context by
+ * appending the buildpath type to which the node belongs. For instance, a compile-time project dependency will be
+ * assigned the request context "project/compile".
+ * <p>
+ * This class also "bridges" between {@link DependencyScope} and Resolver that uses plain string labels for scopes.
+ *
+ * @see DependencyNode#getRequestContext()
+ */
+public final class ManagedDependencyContextRefiner implements DependencyGraphTransformer {
+ private final InternalScopeManager scopeManager;
+
+ public ManagedDependencyContextRefiner(InternalScopeManager scopeManager) {
+ this.scopeManager = requireNonNull(scopeManager, "scopeManager");
+ }
+
+ @Override
+ public DependencyNode transformGraph(DependencyNode node, DependencyGraphTransformationContext context) {
+ requireNonNull(node, "node cannot be null");
+ requireNonNull(context, "context cannot be null");
+ String ctx = node.getRequestContext();
+
+ if ("project".equals(ctx)) {
+ String scope = getBuildpathScope(node);
+ if (scope != null) {
+ ctx += '/' + scope;
+ node.setRequestContext(ctx);
+ }
+ }
+
+ for (DependencyNode child : node.getChildren()) {
+ transformGraph(child, context);
+ }
+
+ return node;
+ }
+
+ private String getBuildpathScope(DependencyNode node) {
+ Dependency dependency = node.getDependency();
+ if (dependency == null) {
+ return null;
+ }
+
+ return scopeManager
+ .getDependencyScope(dependency.getScope())
+ .flatMap(s ->
+ scopeManager.getDependencyScopeMainProjectBuildScope(s).map(BuildScope::getId))
+ .orElse(null);
+ }
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ManagedScopeDeriver.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ManagedScopeDeriver.java
new file mode 100644
index 00000000..c36667c0
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ManagedScopeDeriver.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.internal.impl.scope;
+
+import org.eclipse.aether.impl.scope.InternalScopeManager;
+import org.eclipse.aether.scope.DependencyScope;
+import org.eclipse.aether.scope.ScopeManager;
+import org.eclipse.aether.util.graph.transformer.ConflictResolver;
+import org.eclipse.aether.util.graph.transformer.ConflictResolver.ScopeContext;
+import org.eclipse.aether.util.graph.transformer.ConflictResolver.ScopeDeriver;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A scope deriver for use with {@link ConflictResolver} that supports the scopes from {@link ScopeManager}. It basically
+ * chooses "narrowest" scope, based on parent and child scopes.
+ * <p>
+ * This class also "bridges" between {@link DependencyScope} and Resolver that uses plain string labels for scopes.
+ *
+ * @since 4.0.0
+ */
+public final class ManagedScopeDeriver extends ScopeDeriver {
+ private final InternalScopeManager scopeManager;
+ private final DependencyScope systemScope;
+
+ public ManagedScopeDeriver(InternalScopeManager scopeManager) {
+ this.scopeManager = requireNonNull(scopeManager, "scopeManager");
+ this.systemScope = scopeManager.getSystemScope().orElse(null);
+ }
+
+ @Override
+ public void deriveScope(ScopeContext context) {
+ context.setDerivedScope(getDerivedScope(context.getParentScope(), context.getChildScope()));
+ }
+
+ /**
+ * Visible for testing. It chooses "narrowest" scope out of parent or child, unless child is system scope.
+ */
+ public String getDerivedScope(String parentScope, String childScope) {
+ // ask parent scope (nullable)
+ DependencyScope parent = parentScope != null
+ ? scopeManager.getDependencyScope(parentScope).orElse(null)
+ : null;
+ // ask child scope (non-nullable, but may be unknown scope to manager)
+ DependencyScope child = scopeManager.getDependencyScope(childScope).orElse(null);
+
+ // if system scope exists and child is system scope: system
+ if (systemScope != null && systemScope == child) {
+ return systemScope.getId();
+ }
+ // if no parent (i.e. is root): child scope as-is
+ if (parent == null) {
+ return child != null ? child.getId() : "";
+ }
+ if (child == null) {
+ return parent.getId();
+ }
+ // otherwise the narrowest out of parent or child
+ int parentWidth = scopeManager.getDependencyScopeWidth(parent);
+ int childWidth = scopeManager.getDependencyScopeWidth(child);
+ if (parentWidth < childWidth) {
+ return parent.getId();
+ } else {
+ return child.getId();
+ }
+ }
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ManagedScopeSelector.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ManagedScopeSelector.java
new file mode 100644
index 00000000..c3367091
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ManagedScopeSelector.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.internal.impl.scope;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.eclipse.aether.impl.scope.InternalScopeManager;
+import org.eclipse.aether.scope.DependencyScope;
+import org.eclipse.aether.scope.ScopeManager;
+import org.eclipse.aether.util.graph.transformer.ConflictResolver;
+import org.eclipse.aether.util.graph.transformer.ConflictResolver.ConflictContext;
+import org.eclipse.aether.util.graph.transformer.ConflictResolver.ConflictItem;
+import org.eclipse.aether.util.graph.transformer.ConflictResolver.ScopeSelector;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A scope selector for use with {@link ConflictResolver} that supports the scopes from {@link ScopeManager}.
+ * In general, this selector picks the widest scope present among conflicting dependencies where e.g. "compile" is
+ * wider than "runtime" which is wider than "test". If however a direct dependency is involved, its scope is selected.
+ * <p>
+ * This class also "bridges" between {@link DependencyScope} and Resolver that uses plain string labels for scopes.
+ */
+public final class ManagedScopeSelector extends ScopeSelector {
+ private final DependencyScope systemScope;
+ private final List<DependencyScope> dependencyScopesByWidthDescending;
+
+ public ManagedScopeSelector(InternalScopeManager scopeManager) {
+ requireNonNull(scopeManager, "scopeManager");
+ this.systemScope = scopeManager.getSystemScope().orElse(null);
+ this.dependencyScopesByWidthDescending =
+ Collections.unmodifiableList(scopeManager.getDependencyScopeUniverse().stream()
+ .sorted(Comparator.comparing(scopeManager::getDependencyScopeWidth)
+ .reversed())
+ .collect(Collectors.toList()));
+ }
+
+ @Override
+ public void selectScope(ConflictContext context) {
+ String scope = context.getWinner().getDependency().getScope();
+ if (systemScope == null || !systemScope.getId().equals(scope)) {
+ scope = chooseEffectiveScope(context.getItems());
+ }
+ context.setScope(scope);
+ }
+
+ private String chooseEffectiveScope(Collection<ConflictItem> items) {
+ Set<String> scopes = new HashSet<>();
+ for (ConflictItem item : items) {
+ if (item.getDepth() <= 1) {
+ return item.getDependency().getScope();
+ }
+ scopes.addAll(item.getScopes());
+ }
+ return chooseEffectiveScope(scopes);
+ }
+
+ /**
+ * Visible for testing. It chooses "widest" scope out of provided ones, unless system scope is present, in which
+ * case system scope is selected.
+ */
+ public String chooseEffectiveScope(Set<String> scopes) {
+ if (scopes.size() > 1 && systemScope != null) {
+ scopes.remove(systemScope.getId());
+ }
+
+ String effectiveScope = "";
+
+ if (scopes.size() == 1) {
+ effectiveScope = scopes.iterator().next();
+ } else {
+ for (DependencyScope dependencyScope : dependencyScopesByWidthDescending) {
+ if (scopes.contains(dependencyScope.getId())) {
+ effectiveScope = dependencyScope.getId();
+ break;
+ }
+ }
+ }
+
+ return effectiveScope;
+ }
+}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/OptionalDependencySelector.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/OptionalDependencySelector.java
similarity index 55%
copy from maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/OptionalDependencySelector.java
copy to maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/OptionalDependencySelector.java
index 64c5abfc..7c0c324f 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/OptionalDependencySelector.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/OptionalDependencySelector.java
@@ -16,7 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.eclipse.aether.util.graph.selector;
+package org.eclipse.aether.internal.impl.scope;
+
+import java.util.Objects;
import org.eclipse.aether.collection.DependencyCollectionContext;
import org.eclipse.aether.collection.DependencySelector;
@@ -25,37 +27,58 @@ import org.eclipse.aether.graph.Dependency;
import static java.util.Objects.requireNonNull;
/**
- * A dependency selector that excludes optional dependencies which occur beyond level one of the dependency graph.
+ * A dependency selector that excludes optional dependencies which occur beyond given level.
+ * <p>
+ * <em>Important note:</em> equals/hashCode must factor in starting state, as instances of this class
+ * (potentially differentially configured) are used now in session, but are kept in a set.
*
* @see Dependency#isOptional()
*/
public final class OptionalDependencySelector implements DependencySelector {
+ /**
+ * Excludes optional dependencies always (from root).
+ */
+ public static OptionalDependencySelector fromRoot() {
+ return from(1);
+ }
- private final int depth;
+ /**
+ * Excludes optional transitive dependencies of direct dependencies.
+ */
+ public static OptionalDependencySelector fromDirect() {
+ return from(2);
+ }
/**
- * Creates a new selector to exclude optional transitive dependencies.
+ * Excludes optional transitive dependencies from given depth (1=root, 2=direct, 3=transitives of direct ones...).
*/
- public OptionalDependencySelector() {
- depth = 0;
+ public static OptionalDependencySelector from(int applyFrom) {
+ if (applyFrom < 1) {
+ throw new IllegalArgumentException("applyFrom must be non-zero and positive");
+ }
+ return new OptionalDependencySelector(Objects.hash(applyFrom), 0, applyFrom);
}
- private OptionalDependencySelector(int depth) {
+ private final int seed;
+ private final int depth;
+ private final int applyFrom;
+
+ private OptionalDependencySelector(int seed, int depth, int applyFrom) {
+ this.seed = seed;
this.depth = depth;
+ this.applyFrom = applyFrom;
}
+ @Override
public boolean selectDependency(Dependency dependency) {
requireNonNull(dependency, "dependency cannot be null");
- return depth < 2 || !dependency.isOptional();
+ return depth < applyFrom || !dependency.isOptional();
}
+ @Override
public DependencySelector deriveChildSelector(DependencyCollectionContext context) {
requireNonNull(context, "context cannot be null");
- if (depth >= 2) {
- return this;
- }
-
- return new OptionalDependencySelector(depth + 1);
+ return new OptionalDependencySelector(seed, depth + 1, applyFrom);
}
@Override
@@ -67,18 +90,20 @@ public final class OptionalDependencySelector implements DependencySelector {
}
OptionalDependencySelector that = (OptionalDependencySelector) obj;
- return depth == that.depth;
+ return seed == that.seed && depth == that.depth && applyFrom == that.applyFrom;
}
@Override
public int hashCode() {
int hash = getClass().hashCode();
+ hash = hash * 31 + seed;
hash = hash * 31 + depth;
+ hash = hash * 31 + applyFrom;
return hash;
}
@Override
public String toString() {
- return String.format("%s(depth: %d)", this.getClass().getSimpleName(), this.depth);
+ return String.format("%s(applied: %s)", this.getClass().getSimpleName(), depth >= applyFrom);
}
}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ScopeDependencySelector.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ScopeDependencySelector.java
new file mode 100644
index 00000000..2f450c94
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ScopeDependencySelector.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.internal.impl.scope;
+
+import java.util.Collection;
+import java.util.Objects;
+
+import org.eclipse.aether.collection.DependencyCollectionContext;
+import org.eclipse.aether.collection.DependencySelector;
+import org.eclipse.aether.graph.Dependency;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A dependency selector that filters transitive dependencies based on their scope. It is configurable from which level
+ * applies, as it depend on "as project" and "as dependency" use cases.
+ * <p>
+ * <em>Important note:</em> equals/hashCode must factor in starting state, as instances of this class
+ * (potentially differentially configured) are used now in session, but are kept in a set.
+ * <p>
+ * <em>Note:</em> This filter does not assume any relationships between the scopes.
+ * In particular, the filter is not aware of scopes that logically include other scopes.
+ *
+ * @see Dependency#getScope()
+ */
+public final class ScopeDependencySelector implements DependencySelector {
+ /**
+ * This enables "legacy" mode (proper): in Resolver 1.x "transitive" state depended on the presence or
+ * absence of the root node.
+ */
+ public static ScopeDependencySelector legacy(Collection<String> included, Collection<String> excluded) {
+ return new ScopeDependencySelector(
+ Objects.hash(true, 0, 1, Integer.MAX_VALUE, included, excluded),
+ true,
+ 0,
+ 1,
+ Integer.MAX_VALUE,
+ included,
+ excluded);
+ }
+
+ /**
+ * Selects dependencies by scope always (from root).
+ */
+ public static ScopeDependencySelector fromRoot(Collection<String> included, Collection<String> excluded) {
+ return from(1, included, excluded);
+ }
+
+ /**
+ * Selects dependencies by scope starting from direct dependencies.
+ */
+ public static ScopeDependencySelector fromDirect(Collection<String> included, Collection<String> excluded) {
+ return from(2, included, excluded);
+ }
+
+ /**
+ * Selects dependencies by scope starting from given depth (1=root, 2=direct, 3=transitives of direct ones...).
+ */
+ public static ScopeDependencySelector from(
+ int applyFrom, Collection<String> included, Collection<String> excluded) {
+ return fromTo(applyFrom, Integer.MAX_VALUE, included, excluded);
+ }
+
+ /**
+ * Selects dependencies by scope starting from given depth (1=root, 2=direct, 3=transitives of direct ones...) to
+ * given depth.
+ */
+ public static ScopeDependencySelector fromTo(
+ int applyFrom, int applyTo, Collection<String> included, Collection<String> excluded) {
+ if (applyFrom < 1) {
+ throw new IllegalArgumentException("applyFrom must be non-zero and positive");
+ }
+ if (applyFrom > applyTo) {
+ throw new IllegalArgumentException("applyTo must be greater or equal than applyFrom");
+ }
+ return new ScopeDependencySelector(
+ Objects.hash(false, 0, applyFrom, applyTo, included, excluded),
+ false,
+ 0,
+ applyFrom,
+ applyTo,
+ included,
+ excluded);
+ }
+
+ private final int seed;
+ private final boolean shiftIfRootNull;
+ private final int depth;
+ private final int applyFrom;
+ private final int applyTo;
+ private final Collection<String> included;
+ private final Collection<String> excluded;
+
+ private ScopeDependencySelector(
+ int seed,
+ boolean shiftIfRootNull,
+ int depth,
+ int applyFrom,
+ int applyTo,
+ Collection<String> included,
+ Collection<String> excluded) {
+ this.seed = seed;
+ this.shiftIfRootNull = shiftIfRootNull;
+ this.depth = depth;
+ this.applyFrom = applyFrom;
+ this.applyTo = applyTo;
+ this.included = included;
+ this.excluded = excluded;
+ }
+
+ @Override
+ public boolean selectDependency(Dependency dependency) {
+ requireNonNull(dependency, "dependency cannot be null");
+ if (depth < applyFrom || depth > applyTo) {
+ return true;
+ }
+
+ String scope = dependency.getScope();
+ return (included == null || included.contains(scope)) && (excluded == null || !excluded.contains(scope));
+ }
+
+ @Override
+ public DependencySelector deriveChildSelector(DependencyCollectionContext context) {
+ requireNonNull(context, "context cannot be null");
+ if (depth == 0 && shiftIfRootNull && context.getDependency() == null) {
+ return new ScopeDependencySelector(
+ seed, shiftIfRootNull, depth + 1, applyFrom + 1, applyTo, included, excluded);
+ } else {
+ return new ScopeDependencySelector(
+ seed, shiftIfRootNull, depth + 1, applyFrom, applyTo, included, excluded);
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ } else if (null == obj || !getClass().equals(obj.getClass())) {
+ return false;
+ }
+
+ ScopeDependencySelector that = (ScopeDependencySelector) obj;
+ return seed == that.seed
+ && shiftIfRootNull == that.shiftIfRootNull
+ && depth == that.depth
+ && applyFrom == that.applyFrom
+ && applyTo == that.applyTo
+ && Objects.equals(included, that.included)
+ && Objects.equals(excluded, that.excluded);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 17;
+ hash = hash * 31 + seed;
+ hash = hash * 31 + (shiftIfRootNull ? 0 : 1);
+ hash = hash * 31 + depth;
+ hash = hash * 31 + applyFrom;
+ hash = hash * 31 + applyTo;
+ hash = hash * 31 + (included != null ? included.hashCode() : 0);
+ hash = hash * 31 + (excluded != null ? excluded.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ "%s(included: %s, excluded: %s, applied: %s)",
+ getClass().getSimpleName(), included, excluded, depth >= applyFrom);
+ }
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ScopeManagerDump.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ScopeManagerDump.java
new file mode 100644
index 00000000..22ef7bcf
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ScopeManagerDump.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.internal.impl.scope;
+
+import java.util.Comparator;
+import java.util.stream.Collectors;
+
+import org.eclipse.aether.impl.scope.BuildScope;
+import org.eclipse.aether.impl.scope.ScopeManagerConfiguration;
+import org.eclipse.aether.scope.ResolutionScope;
+
+import static org.eclipse.aether.impl.scope.BuildScopeQuery.all;
+
+/**
+ * This is a diagnostic tool to dump out scope manager states.
+ */
+public final class ScopeManagerDump {
+
+ /**
+ * Invoke this method with configuration and this class will dump its interpretation.
+ */
+ public static void dump(ScopeManagerConfiguration configuration) {
+ new ScopeManagerDump(configuration);
+ }
+
+ private ScopeManagerDump(ScopeManagerConfiguration configuration) {
+ ScopeManagerImpl scopeManager = new ScopeManagerImpl(configuration);
+ System.out.println();
+ dumpBuildScopes(scopeManager);
+ System.out.println();
+ dumpDependencyScopes(scopeManager);
+ System.out.println();
+ dumpDependencyScopeDerives(scopeManager);
+ System.out.println();
+ dumpResolutionScopes(scopeManager);
+ }
+
+ private void dumpBuildScopes(ScopeManagerImpl scopeManager) {
+ System.out.println(scopeManager.getId() + " defined build scopes:");
+ scopeManager.getBuildScopeSource().query(all()).stream()
+ .sorted(Comparator.comparing(BuildScope::order))
+ .forEach(s -> System.out.println(s.getId() + " (order=" + s.order() + ")"));
+ }
+
+ private void dumpDependencyScopes(ScopeManagerImpl scopeManager) {
+ System.out.println(scopeManager.getId() + " defined dependency scopes:");
+ scopeManager.getDependencyScopeUniverse().stream()
+ .sorted(Comparator.comparing(scopeManager::getDependencyScopeWidth)
+ .reversed())
+ .forEach(s -> {
+ System.out.println(s + " (width=" + scopeManager.getDependencyScopeWidth(s) + ")");
+ System.out.println(" Query : " + scopeManager.getPresence(s));
+ System.out.println(" Presence: "
+ + scopeManager.getBuildScopeSource().query(scopeManager.getPresence(s)).stream()
+ .map(BuildScope::getId)
+ .collect(Collectors.toSet()));
+ System.out.println(" Main project scope: "
+ + scopeManager
+ .getDependencyScopeMainProjectBuildScope(s)
+ .map(BuildScope::getId)
+ .orElse("null"));
+ });
+ }
+
+ private void dumpDependencyScopeDerives(ScopeManagerImpl scopeManager) {
+ System.out.println(scopeManager.getId() + " defined dependency derive matrix:");
+ ManagedScopeDeriver deriver = new ManagedScopeDeriver(scopeManager);
+ scopeManager.getDependencyScopeUniverse().stream()
+ .sorted(Comparator.comparing(scopeManager::getDependencyScopeWidth)
+ .reversed())
+ .forEach(parent -> scopeManager.getDependencyScopeUniverse().stream()
+ .sorted(Comparator.comparing(scopeManager::getDependencyScopeWidth)
+ .reversed())
+ .forEach(child -> System.out.println(parent.getId() + " w/ child " + child.getId() + " -> "
+ + deriver.getDerivedScope(parent.getId(), child.getId()))));
+ }
+
+ private void dumpResolutionScopes(ScopeManagerImpl scopeManager) {
+ System.out.println(scopeManager.getId() + " defined resolution scopes:");
+ scopeManager.getResolutionScopeUniverse().stream()
+ .sorted(Comparator.comparing(ResolutionScope::getId))
+ .forEach(s -> {
+ System.out.println("* " + s.getId());
+ System.out.println(" Directly included: " + scopeManager.getDirectlyIncludedLabels(s));
+ System.out.println(" Directly excluded: " + scopeManager.getDirectlyExcludedLabels(s));
+ System.out.println(" Transitively excluded: " + scopeManager.getTransitivelyExcludedLabels(s));
+ });
+ }
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ScopeManagerImpl.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ScopeManagerImpl.java
new file mode 100644
index 00000000..ea49c5b8
--- /dev/null
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/scope/ScopeManagerImpl.java
@@ -0,0 +1,480 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.internal.impl.scope;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.collection.CollectResult;
+import org.eclipse.aether.collection.DependencyGraphTransformer;
+import org.eclipse.aether.collection.DependencySelector;
+import org.eclipse.aether.graph.DependencyFilter;
+import org.eclipse.aether.impl.scope.BuildPath;
+import org.eclipse.aether.impl.scope.BuildScope;
+import org.eclipse.aether.impl.scope.BuildScopeQuery;
+import org.eclipse.aether.impl.scope.BuildScopeSource;
+import org.eclipse.aether.impl.scope.InternalScopeManager;
+import org.eclipse.aether.impl.scope.ProjectPath;
+import org.eclipse.aether.impl.scope.ScopeManagerConfiguration;
+import org.eclipse.aether.scope.DependencyScope;
+import org.eclipse.aether.scope.ResolutionScope;
+import org.eclipse.aether.scope.SystemDependencyScope;
+import org.eclipse.aether.util.filter.ScopeDependencyFilter;
+import org.eclipse.aether.util.graph.selector.AndDependencySelector;
+import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector;
+import org.eclipse.aether.util.graph.transformer.ChainedDependencyGraphTransformer;
+import org.eclipse.aether.util.graph.transformer.ConflictResolver;
+import org.eclipse.aether.util.graph.transformer.NearestVersionSelector;
+import org.eclipse.aether.util.graph.transformer.SimpleOptionalitySelector;
+import org.eclipse.aether.util.graph.visitor.CloningDependencyVisitor;
+import org.eclipse.aether.util.graph.visitor.FilteringDependencyVisitor;
+
+import static java.util.Objects.requireNonNull;
+
+public final class ScopeManagerImpl implements InternalScopeManager {
+ private final String id;
+ private final boolean strictDependencyScopes;
+ private final boolean strictResolutionScopes;
+ private final BuildScopeSource buildScopeSource;
+ private final AtomicReference<SystemDependencyScopeImpl> systemDependencyScope;
+ private final Map<String, DependencyScopeImpl> dependencyScopes;
+ private final Map<String, ResolutionScopeImpl> resolutionScopes;
+
+ public ScopeManagerImpl(ScopeManagerConfiguration configuration) {
+ this.id = configuration.getId();
+ this.strictDependencyScopes = configuration.isStrictDependencyScopes();
+ this.strictResolutionScopes = configuration.isStrictResolutionScopes();
+ this.buildScopeSource = configuration.getBuildScopeSource();
+ this.systemDependencyScope = new AtomicReference<>(null);
+ this.dependencyScopes = Collections.unmodifiableMap(buildDependencyScopes(configuration));
+ this.resolutionScopes = Collections.unmodifiableMap(buildResolutionScopes(configuration));
+ }
+
+ private Map<String, DependencyScopeImpl> buildDependencyScopes(ScopeManagerConfiguration configuration) {
+ Collection<DependencyScope> dependencyScopes = configuration.buildDependencyScopes(this);
+ HashMap<String, DependencyScopeImpl> result = new HashMap<>(dependencyScopes.size());
+ dependencyScopes.forEach(d -> result.put(d.getId(), (DependencyScopeImpl) d));
+ return result;
+ }
+
+ private Map<String, ResolutionScopeImpl> buildResolutionScopes(ScopeManagerConfiguration configuration) {
+ Collection<ResolutionScope> resolutionScopes = configuration.buildResolutionScopes(this);
+ HashMap<String, ResolutionScopeImpl> result = new HashMap<>(resolutionScopes.size());
+ resolutionScopes.forEach(r -> result.put(r.getId(), (ResolutionScopeImpl) r));
+ return result;
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public Optional<SystemDependencyScope> getSystemScope() {
+ return Optional.ofNullable(systemDependencyScope.get());
+ }
+
+ @Override
+ public Optional<DependencyScope> getDependencyScope(String id) {
+ DependencyScope dependencyScope = dependencyScopes.get(id);
+ if (strictDependencyScopes && dependencyScope == null) {
+ throw new IllegalArgumentException("unknown dependency scope");
+ }
+ return Optional.ofNullable(dependencyScope);
+ }
+
+ @Override
+ public Collection<DependencyScope> getDependencyScopeUniverse() {
+ return new HashSet<>(dependencyScopes.values());
+ }
+
+ @Override
+ public Optional<ResolutionScope> getResolutionScope(String id) {
+ ResolutionScope resolutionScope = resolutionScopes.get(id);
+ if (strictResolutionScopes && resolutionScope == null) {
+ throw new IllegalArgumentException("unknown resolution scope");
+ }
+ return Optional.ofNullable(resolutionScope);
+ }
+
+ @Override
+ public Collection<ResolutionScope> getResolutionScopeUniverse() {
+ return new HashSet<>(resolutionScopes.values());
+ }
+
+ @Override
+ public int getDependencyScopeWidth(DependencyScope dependencyScope) {
+ return translate(dependencyScope).getWidth();
+ }
+
+ @Override
+ public Optional<BuildScope> getDependencyScopeMainProjectBuildScope(DependencyScope dependencyScope) {
+ return Optional.ofNullable(translate(dependencyScope).getMainBuildScope());
+ }
+
+ @Override
+ public DependencySelector getDependencySelector(ResolutionScope resolutionScope) {
+ ResolutionScopeImpl rs = translate(resolutionScope);
+ Set<String> directlyExcludedLabels = getDirectlyExcludedLabels(rs);
+ Set<String> transitivelyExcludedLabels = getTransitivelyExcludedLabels(rs);
+
+ return new AndDependencySelector(
+ rs.getMode() == Mode.ELIMINATE
+ ? ScopeDependencySelector.fromTo(2, 2, null, directlyExcludedLabels)
+ : ScopeDependencySelector.fromTo(1, 2, null, directlyExcludedLabels),
+ ScopeDependencySelector.from(2, null, transitivelyExcludedLabels),
+ OptionalDependencySelector.fromDirect(),
+ new ExclusionDependencySelector());
+ }
+
+ @Override
+ public DependencyGraphTransformer getDependencyGraphTransformer(ResolutionScope resolutionScope) {
+ return new ChainedDependencyGraphTransformer(
+ new ConflictResolver(
+ new NearestVersionSelector(), new ManagedScopeSelector(this),
+ new SimpleOptionalitySelector(), new ManagedScopeDeriver(this)),
+ new ManagedDependencyContextRefiner(this));
+ }
+
+ @Override
+ public CollectResult postProcess(ResolutionScope resolutionScope, CollectResult collectResult) {
+ ResolutionScopeImpl rs = translate(resolutionScope);
+ if (rs.getMode() == Mode.ELIMINATE) {
+ CloningDependencyVisitor cloning = new CloningDependencyVisitor();
+ FilteringDependencyVisitor filter = new FilteringDependencyVisitor(
+ cloning, new ScopeDependencyFilter(null, getDirectlyExcludedLabels(rs)));
+ collectResult.getRoot().accept(filter);
+ collectResult.setRoot(cloning.getRootNode());
+ }
+ return collectResult;
+ }
+
+ @Override
+ public DependencyFilter getDependencyFilter(ResolutionScope resolutionScope) {
+ return new ScopeDependencyFilter(null, getDirectlyExcludedLabels(translate(resolutionScope)));
+ }
+
+ @Override
+ public DependencyScope createDependencyScope(String id, boolean transitive, Collection<BuildScopeQuery> presence) {
+ return new DependencyScopeImpl(id, transitive, presence);
+ }
+
+ @Override
+ public SystemDependencyScope createSystemDependencyScope(
+ String id, boolean transitive, Collection<BuildScopeQuery> presence, String systemPathProperty) {
+ SystemDependencyScopeImpl system = new SystemDependencyScopeImpl(id, transitive, presence, systemPathProperty);
+ if (systemDependencyScope.compareAndSet(null, system)) {
+ return system;
+ } else {
+ throw new IllegalStateException("system dependency scope already created");
+ }
+ }
+
+ @Override
+ public ResolutionScope createResolutionScope(
+ String id,
+ Mode mode,
+ Collection<BuildScopeQuery> wantedPresence,
+ Collection<DependencyScope> explicitlyIncluded,
+ Collection<DependencyScope> transitivelyExcluded) {
+ return new ResolutionScopeImpl(id, mode, wantedPresence, explicitlyIncluded, transitivelyExcluded);
+ }
+
+ private Set<DependencyScope> collectScopes(Collection<BuildScopeQuery> wantedPresence) {
+ HashSet<DependencyScope> result = new HashSet<>();
+ for (BuildScope buildScope : buildScopeSource.query(wantedPresence)) {
+ dependencyScopes.values().stream()
+ .filter(s -> buildScopeSource.query(s.getPresence()).contains(buildScope))
+ .filter(s -> systemDependencyScope.get() == null
+ || !systemDependencyScope.get().is(s.id)) // system scope must be always explicitly added
+ .forEach(result::add);
+ }
+ return result;
+ }
+
+ private int calculateDependencyScopeWidth(DependencyScopeImpl dependencyScope) {
+ int result = 0;
+ if (dependencyScope.isTransitive()) {
+ result += 1000;
+ }
+ for (BuildScope buildScope : buildScopeSource.query(dependencyScope.getPresence())) {
+ result += 1000
+ / buildScope.getProjectPaths().stream()
+ .map(ProjectPath::order)
+ .reduce(0, Integer::sum);
+ }
+ return result;
+ }
+
+ private BuildScope calculateMainProjectBuildScope(DependencyScopeImpl dependencyScope) {
+ for (ProjectPath projectPath : buildScopeSource.allProjectPaths().stream()
+ .sorted(Comparator.comparing(ProjectPath::order))
+ .collect(Collectors.toList())) {
+ for (BuildPath buildPath : buildScopeSource.allBuildPaths().stream()
+ .sorted(Comparator.comparing(BuildPath::order))
+ .collect(Collectors.toList())) {
+ for (BuildScope buildScope : buildScopeSource.query(dependencyScope.getPresence())) {
+ if (buildScope.getProjectPaths().contains(projectPath)
+ && buildScope.getBuildPaths().contains(buildPath)) {
+ return buildScope;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Visible for testing.
+ */
+ Set<String> getDirectlyIncludedLabels(ResolutionScope resolutionScope) {
+ return translate(resolutionScope).getDirectlyIncluded().stream()
+ .map(DependencyScope::getId)
+ .collect(Collectors.toSet());
+ }
+
+ /**
+ * Visible for testing.
+ */
+ Set<String> getDirectlyExcludedLabels(ResolutionScope resolutionScope) {
+ ResolutionScopeImpl rs = translate(resolutionScope);
+ return dependencyScopes.values().stream()
+ .filter(s -> !rs.getDirectlyIncluded().contains(s))
+ .map(DependencyScope::getId)
+ .collect(Collectors.toSet());
+ }
+
+ /**
+ * Visible for testing.
+ */
+ Set<String> getTransitivelyExcludedLabels(ResolutionScope resolutionScope) {
+ return translate(resolutionScope).getTransitivelyExcluded().stream()
+ .map(DependencyScope::getId)
+ .collect(Collectors.toSet());
+ }
+
+ /**
+ * Visible for testing.
+ */
+ Set<BuildScopeQuery> getPresence(DependencyScope dependencyScope) {
+ return translate(dependencyScope).getPresence();
+ }
+
+ /**
+ * Visible for testing.
+ */
+ BuildScopeSource getBuildScopeSource() {
+ return buildScopeSource;
+ }
+
+ private DependencyScopeImpl translate(DependencyScope dependencyScope) {
+ return requireNonNull(dependencyScopes.get(dependencyScope.getId()), "unknown dependency scope");
+ }
+
+ private ResolutionScopeImpl translate(ResolutionScope resolutionScope) {
+ return requireNonNull(resolutionScopes.get(resolutionScope.getId()), "unknown resolution scope");
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ScopeManagerImpl that = (ScopeManagerImpl) o;
+ return Objects.equals(id, that.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+
+ @Override
+ public String toString() {
+ return id;
+ }
+
+ private class DependencyScopeImpl implements DependencyScope {
+ private final String id;
+ private final boolean transitive;
+ private final Set<BuildScopeQuery> presence;
+ private final BuildScope mainBuildScope;
+ private final int width;
+
+ private DependencyScopeImpl(String id, boolean transitive, Collection<BuildScopeQuery> presence) {
+ this.id = requireNonNull(id, "id");
+ this.transitive = transitive;
+ this.presence = Collections.unmodifiableSet(new HashSet<>(presence));
+ this.mainBuildScope = calculateMainProjectBuildScope(this);
+ this.width = calculateDependencyScopeWidth(this);
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public boolean isTransitive() {
+ return transitive;
+ }
+
+ public Set<BuildScopeQuery> getPresence() {
+ return presence;
+ }
+
+ public BuildScope getMainBuildScope() {
+ return mainBuildScope;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DependencyScopeImpl that = (DependencyScopeImpl) o;
+ return Objects.equals(id, that.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+
+ @Override
+ public String toString() {
+ return id;
+ }
+ }
+
+ private class SystemDependencyScopeImpl extends DependencyScopeImpl implements SystemDependencyScope {
+ private final String systemPathProperty;
+
+ private SystemDependencyScopeImpl(
+ String id, boolean transitive, Collection<BuildScopeQuery> presence, String systemPathProperty) {
+ super(id, transitive, presence);
+ this.systemPathProperty = requireNonNull(systemPathProperty);
+ }
+
+ @Override
+ public String getSystemPath(Artifact artifact) {
+ return artifact.getProperty(systemPathProperty, null);
+ }
+
+ @Override
+ public void setSystemPath(Map<String, String> properties, String systemPath) {
+ if (systemPath == null) {
+ properties.remove(systemPathProperty);
+ } else {
+ properties.put(systemPathProperty, systemPath);
+ }
+ }
+ }
+
+ private class ResolutionScopeImpl implements ResolutionScope {
+
+ private final String id;
+ private final Mode mode;
+ private final Set<BuildScopeQuery> wantedPresence;
+ private final Set<DependencyScope> directlyIncluded;
+ private final Set<DependencyScope> transitivelyExcluded;
+
+ private ResolutionScopeImpl(
+ String id,
+ Mode mode,
+ Collection<BuildScopeQuery> wantedPresence,
+ Collection<DependencyScope> explicitlyIncluded,
+ Collection<DependencyScope> transitivelyExcluded) {
+ this.id = requireNonNull(id, "id");
+ this.mode = requireNonNull(mode, "mode");
+ this.wantedPresence = Collections.unmodifiableSet(new HashSet<>(wantedPresence));
+ Set<DependencyScope> included = collectScopes(wantedPresence);
+ // here we may have null elements, based on existence of system scope
+ if (explicitlyIncluded != null && !explicitlyIncluded.isEmpty()) {
+ explicitlyIncluded.stream().filter(Objects::nonNull).forEach(included::add);
+ }
+ this.directlyIncluded = Collections.unmodifiableSet(included);
+ this.transitivelyExcluded = Collections.unmodifiableSet(
+ transitivelyExcluded.stream().filter(Objects::nonNull).collect(Collectors.toSet()));
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ public Mode getMode() {
+ return mode;
+ }
+
+ public Set<BuildScopeQuery> getWantedPresence() {
+ return wantedPresence;
+ }
+
+ public Set<DependencyScope> getDirectlyIncluded() {
+ return directlyIncluded;
+ }
+
+ public Set<DependencyScope> getTransitivelyExcluded() {
+ return transitivelyExcluded;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ResolutionScopeImpl that = (ResolutionScopeImpl) o;
+ return Objects.equals(id, that.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+
+ @Override
+ public String toString() {
+ return id;
+ }
+ }
+}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/session/DefaultCloseableSession.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/session/DefaultCloseableSession.java
index dc808690..03f502c0 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/session/DefaultCloseableSession.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/session/DefaultCloseableSession.java
@@ -38,6 +38,8 @@ import org.eclipse.aether.repository.ProxySelector;
import org.eclipse.aether.repository.WorkspaceReader;
import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
import org.eclipse.aether.resolution.ResolutionErrorPolicy;
+import org.eclipse.aether.scope.ScopeManager;
+import org.eclipse.aether.scope.SystemDependencyScope;
import org.eclipse.aether.transfer.TransferListener;
import org.eclipse.aether.util.listener.ChainedRepositoryListener;
import org.eclipse.aether.util.listener.ChainedTransferListener;
@@ -102,7 +104,7 @@ public final class DefaultCloseableSession implements CloseableSession {
private final RepositoryCache cache;
- private final SystemScopeHandler systemScopeHandler;
+ private final ScopeManager scopeManager;
private final RepositorySystem repositorySystem;
@@ -137,7 +139,7 @@ public final class DefaultCloseableSession implements CloseableSession {
DependencyGraphTransformer dependencyGraphTransformer,
SessionData data,
RepositoryCache cache,
- SystemScopeHandler systemScopeHandler,
+ ScopeManager scopeManager,
List<Runnable> onSessionEndedHandlers,
RepositorySystem repositorySystem,
RepositorySystemLifecycle repositorySystemLifecycle) {
@@ -167,7 +169,7 @@ public final class DefaultCloseableSession implements CloseableSession {
this.dependencyGraphTransformer = dependencyGraphTransformer;
this.data = requireNonNull(data);
this.cache = cache;
- this.systemScopeHandler = requireNonNull(systemScopeHandler);
+ this.scopeManager = scopeManager;
this.repositorySystem = requireNonNull(repositorySystem);
this.repositorySystemLifecycle = requireNonNull(repositorySystemLifecycle);
@@ -330,8 +332,17 @@ public final class DefaultCloseableSession implements CloseableSession {
}
@Override
- public SystemScopeHandler getSystemScopeHandler() {
- return systemScopeHandler;
+ public ScopeManager getScopeManager() {
+ return scopeManager;
+ }
+
+ @Override
+ public SystemDependencyScope getSystemDependencyScope() {
+ if (scopeManager != null) {
+ return scopeManager.getSystemScope().orElse(null);
+ } else {
+ return SystemDependencyScope.LEGACY;
+ }
}
@Override
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/session/DefaultSessionBuilder.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/session/DefaultSessionBuilder.java
index 630fdf9e..d50dc0a4 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/session/DefaultSessionBuilder.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/session/DefaultSessionBuilder.java
@@ -30,7 +30,6 @@ import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.RepositorySystemSession.CloseableSession;
import org.eclipse.aether.RepositorySystemSession.SessionBuilder;
import org.eclipse.aether.SessionData;
-import org.eclipse.aether.SystemScopeHandler;
import org.eclipse.aether.artifact.ArtifactTypeRegistry;
import org.eclipse.aether.collection.DependencyGraphTransformer;
import org.eclipse.aether.collection.DependencyManager;
@@ -47,6 +46,7 @@ import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.repository.WorkspaceReader;
import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
import org.eclipse.aether.resolution.ResolutionErrorPolicy;
+import org.eclipse.aether.scope.ScopeManager;
import org.eclipse.aether.transfer.TransferListener;
import static java.util.Objects.requireNonNull;
@@ -126,7 +126,7 @@ public final class DefaultSessionBuilder implements SessionBuilder {
private Supplier<RepositoryCache> repositoryCacheSupplier = DEFAULT_REPOSITORY_CACHE_SUPPLIER;
- private SystemScopeHandler systemScopeHandler = SystemScopeHandler.LEGACY;
+ private ScopeManager scopeManager;
private final ArrayList<Runnable> onSessionCloseHandlers = new ArrayList<>();
@@ -353,9 +353,8 @@ public final class DefaultSessionBuilder implements SessionBuilder {
}
@Override
- public DefaultSessionBuilder setSystemScopeHandler(SystemScopeHandler systemScopeHandler) {
- requireNonNull(systemScopeHandler, "null systemScopeHandler");
- this.systemScopeHandler = systemScopeHandler;
+ public DefaultSessionBuilder setScopeManager(ScopeManager scopeManager) {
+ this.scopeManager = scopeManager;
return this;
}
@@ -447,7 +446,6 @@ public final class DefaultSessionBuilder implements SessionBuilder {
setDependencyGraphTransformer(session.getDependencyGraphTransformer());
setData(session.getData());
setCache(session.getCache());
- setSystemScopeHandler(session.getSystemScopeHandler());
return this;
}
@@ -481,7 +479,7 @@ public final class DefaultSessionBuilder implements SessionBuilder {
dependencyGraphTransformer,
sessionDataSupplier.get(),
repositoryCacheSupplier.get(),
- systemScopeHandler,
+ scopeManager,
onSessionCloseHandlers,
repositorySystem,
repositorySystemLifecycle);
diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DependencyCollectorDelegateTestSupport.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DependencyCollectorDelegateTestSupport.java
index e8d548ff..74672bc4 100644
--- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DependencyCollectorDelegateTestSupport.java
+++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DependencyCollectorDelegateTestSupport.java
@@ -24,7 +24,6 @@ import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystemSession;
-import org.eclipse.aether.SystemScopeHandler;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.ArtifactProperties;
import org.eclipse.aether.artifact.DefaultArtifact;
@@ -70,8 +69,6 @@ import static org.junit.jupiter.api.Assertions.*;
*/
public abstract class DependencyCollectorDelegateTestSupport {
- protected static final SystemScopeHandler SYSTEM_SCOPE_HANDLER = SystemScopeHandler.LEGACY;
-
protected DefaultRepositorySystemSession session;
protected DependencyGraphParser parser;
@@ -382,7 +379,7 @@ public abstract class DependencyCollectorDelegateTestSupport {
Dependency dependency = newDep("managed:aid:ext:ver");
CollectRequest request = new CollectRequest(dependency, singletonList(repository));
- session.setDependencyManager(new ClassicDependencyManager(SYSTEM_SCOPE_HANDLER));
+ session.setDependencyManager(new ClassicDependencyManager(null));
CollectResult result = collector.collectDependencies(session, request);
@@ -457,7 +454,7 @@ public abstract class DependencyCollectorDelegateTestSupport {
void testDependencyManagement_TransitiveDependencyManager() throws DependencyCollectionException, IOException {
collector = setupCollector(newReader("managed/"));
parser = new DependencyGraphParser("artifact-descriptions/managed/");
- session.setDependencyManager(new TransitiveDependencyManager(SYSTEM_SCOPE_HANDLER));
+ session.setDependencyManager(new TransitiveDependencyManager(null));
final Dependency root = newDep("gid:root:ext:ver", "compile");
CollectRequest request = new CollectRequest(root, singletonList(repository));
request.addManagedDependency(newDep("gid:root:ext:must-retain-core-management"));
@@ -474,7 +471,7 @@ public abstract class DependencyCollectorDelegateTestSupport {
rootArtifactRequest.addManagedDependency(newDep("gid:root:ext:must-retain-core-management"));
rootArtifactRequest.addManagedDependency(newDep("gid:direct:ext:must-retain-core-management"));
rootArtifactRequest.addManagedDependency(newDep("gid:transitive-1:ext:managed-by-root"));
- session.setDependencyManager(new TransitiveDependencyManager(SYSTEM_SCOPE_HANDLER));
+ session.setDependencyManager(new TransitiveDependencyManager(null));
result = collector.collectDependencies(session, rootArtifactRequest);
assertEqualSubtree(expectedTree, toDependencyResult(result.getRoot(), "compile", null));
}
@@ -483,7 +480,7 @@ public abstract class DependencyCollectorDelegateTestSupport {
void testDependencyManagement_DefaultDependencyManager() throws DependencyCollectionException, IOException {
collector = setupCollector(newReader("managed/"));
parser = new DependencyGraphParser("artifact-descriptions/managed/");
- session.setDependencyManager(new DefaultDependencyManager(SYSTEM_SCOPE_HANDLER));
+ session.setDependencyManager(new DefaultDependencyManager(null));
final Dependency root = newDep("gid:root:ext:ver", "compile");
CollectRequest request = new CollectRequest(root, singletonList(repository));
request.addManagedDependency(newDep("gid:root:ext:must-not-manage-root"));
@@ -501,7 +498,7 @@ public abstract class DependencyCollectorDelegateTestSupport {
rootArtifactRequest.addManagedDependency(newDep("gid:root:ext:must-not-manage-root"));
rootArtifactRequest.addManagedDependency(newDep("gid:direct:ext:managed-by-dominant-request"));
rootArtifactRequest.addManagedDependency(newDep("gid:transitive-1:ext:managed-by-root"));
- session.setDependencyManager(new DefaultDependencyManager(SYSTEM_SCOPE_HANDLER));
+ session.setDependencyManager(new DefaultDependencyManager(null));
result = collector.collectDependencies(session, rootArtifactRequest);
assertEqualSubtree(expectedTree, toDependencyResult(result.getRoot(), "compile", null));
}
diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/bf/BfWithSkipperDependencyCollectorTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/bf/BfWithSkipperDependencyCollectorTest.java
index 4256d129..5f927b23 100644
--- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/bf/BfWithSkipperDependencyCollectorTest.java
+++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/bf/BfWithSkipperDependencyCollectorTest.java
@@ -69,7 +69,7 @@ public class BfWithSkipperDependencyCollectorTest extends DependencyCollectorDel
void testSkipperWithDifferentExclusion() throws DependencyCollectionException {
collector = setupCollector(newReader("managed/"));
parser = new DependencyGraphParser("artifact-descriptions/managed/");
- session.setDependencyManager(new TransitiveDependencyManager(SYSTEM_SCOPE_HANDLER));
+ session.setDependencyManager(new TransitiveDependencyManager(null));
ExclusionDependencySelector exclSel1 = new ExclusionDependencySelector();
session.setDependencySelector(exclSel1);
diff --git a/maven-resolver-supplier/pom.xml b/maven-resolver-supplier-mvn3/pom.xml
similarity index 91%
copy from maven-resolver-supplier/pom.xml
copy to maven-resolver-supplier-mvn3/pom.xml
index 81de91f2..af411e54 100644
--- a/maven-resolver-supplier/pom.xml
+++ b/maven-resolver-supplier-mvn3/pom.xml
@@ -26,9 +26,9 @@
<version>2.0.0-SNAPSHOT</version>
</parent>
- <artifactId>maven-resolver-supplier</artifactId>
+ <artifactId>maven-resolver-supplier-mvn3</artifactId>
- <name>Maven Artifact Resolver Instance Supplier</name>
+ <name>Maven Artifact Resolver Instance Supplier Maven3</name>
<description>A helper module to provide RepositorySystem instances.</description>
<properties>
@@ -73,7 +73,7 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
- <version>${mavenVersion}</version>
+ <version>${maven3Version}</version>
<exclusions>
<exclusion>
<groupId>javax.inject</groupId>
@@ -96,7 +96,7 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model-builder</artifactId>
- <version>${mavenVersion}</version>
+ <version>${maven3Version}</version>
<exclusions>
<exclusion>
<groupId>javax.inject</groupId>
@@ -121,6 +121,14 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-xml</artifactId>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
diff --git a/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/spi/locator/Service.java b/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/spi/locator/Service.java
new file mode 100644
index 00000000..1b53edf1
--- /dev/null
+++ b/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/spi/locator/Service.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.spi.locator;
+
+/**
+ * This class here is merely to provide backward compatibility to Maven3. Pretend is not here.
+ *
+ * @since 2.0.0
+ */
+@Deprecated
+public interface Service {}
diff --git a/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/spi/locator/ServiceLocator.java b/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/spi/locator/ServiceLocator.java
new file mode 100644
index 00000000..fc79dfdc
--- /dev/null
+++ b/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/spi/locator/ServiceLocator.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.spi.locator;
+
+import java.util.List;
+
+/**
+ * This class here is merely to provide backward compatibility to Maven3. Pretend is not here.
+ *
+ * @since 2.0.0
+ */
+@Deprecated
+public interface ServiceLocator {
+
+ /**
+ * Gets an instance of the specified service.
+ *
+ * @param <T> The service type.
+ * @param type The interface describing the service, must not be {@code null}.
+ * @return The service instance or {@code null} if the service could not be located/initialized.
+ */
+ <T> T getService(Class<T> type);
+
+ /**
+ * Gets all available instances of the specified service.
+ *
+ * @param <T> The service type.
+ * @param type The interface describing the service, must not be {@code null}.
+ * @return The (read-only) list of available service instances, never {@code null}.
+ */
+ <T> List<T> getServices(Class<T> type);
+}
diff --git a/maven-resolver-supplier/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java b/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
similarity index 96%
copy from maven-resolver-supplier/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
copy to maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
index af9bc2a4..6017aa72 100644
--- a/maven-resolver-supplier/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
+++ b/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
@@ -19,16 +19,20 @@
package org.eclipse.aether.supplier;
import java.util.HashMap;
-import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import org.apache.maven.model.building.DefaultModelBuilderFactory;
import org.apache.maven.model.building.ModelBuilder;
-import org.apache.maven.repository.internal.*;
-import org.apache.maven.repository.internal.relocation.DistributionManagementArtifactRelocationSource;
-import org.apache.maven.repository.internal.relocation.UserPropertiesArtifactRelocationSource;
+import org.apache.maven.repository.internal.DefaultArtifactDescriptorReader;
+import org.apache.maven.repository.internal.DefaultModelCacheFactory;
+import org.apache.maven.repository.internal.DefaultVersionRangeResolver;
+import org.apache.maven.repository.internal.DefaultVersionResolver;
+import org.apache.maven.repository.internal.ModelCacheFactory;
+import org.apache.maven.repository.internal.PluginsMetadataGeneratorFactory;
+import org.apache.maven.repository.internal.SnapshotMetadataGeneratorFactory;
+import org.apache.maven.repository.internal.VersionsMetadataGeneratorFactory;
import org.eclipse.aether.RepositoryListener;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
@@ -873,26 +877,6 @@ public class RepositorySystemSupplier implements Supplier<RepositorySystem> {
return result;
}
- private LinkedHashMap<String, MavenArtifactRelocationSource> artifactRelocationSources;
-
- public final LinkedHashMap<String, MavenArtifactRelocationSource> getMavenArtifactRelocationSources() {
- checkClosed();
- if (artifactRelocationSources == null) {
- artifactRelocationSources = createMavenArtifactRelocationSources();
- }
- return artifactRelocationSources;
- }
-
- protected LinkedHashMap<String, MavenArtifactRelocationSource> createMavenArtifactRelocationSources() {
- // from maven-resolver-provider
- LinkedHashMap<String, MavenArtifactRelocationSource> result = new LinkedHashMap<>();
- result.put(UserPropertiesArtifactRelocationSource.NAME, new UserPropertiesArtifactRelocationSource());
- result.put(
- DistributionManagementArtifactRelocationSource.NAME,
- new DistributionManagementArtifactRelocationSource());
- return result;
- }
-
private ArtifactDescriptorReader artifactDescriptorReader;
public final ArtifactDescriptorReader getArtifactDescriptorReader() {
@@ -912,8 +896,7 @@ public class RepositorySystemSupplier implements Supplier<RepositorySystem> {
getArtifactResolver(),
getModelBuilder(),
getRepositoryEventDispatcher(),
- getModelCacheFactory(),
- getMavenArtifactRelocationSources());
+ getModelCacheFactory());
}
private VersionResolver versionResolver;
@@ -945,7 +928,7 @@ public class RepositorySystemSupplier implements Supplier<RepositorySystem> {
protected VersionRangeResolver createVersionRangeResolver() {
// from maven-resolver-provider
return new DefaultVersionRangeResolver(
- getMetadataResolver(), getSyncContextFactory(), getRepositoryEventDispatcher(), getVersionScheme());
+ getMetadataResolver(), getSyncContextFactory(), getRepositoryEventDispatcher());
}
private ModelBuilder modelBuilder;
diff --git a/maven-resolver-supplier/src/main/java/org/eclipse/aether/supplier/SessionBuilderSupplier.java b/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/SessionBuilderSupplier.java
similarity index 90%
rename from maven-resolver-supplier/src/main/java/org/eclipse/aether/supplier/SessionBuilderSupplier.java
rename to maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/SessionBuilderSupplier.java
index 64157356..89fb5f3c 100644
--- a/maven-resolver-supplier/src/main/java/org/eclipse/aether/supplier/SessionBuilderSupplier.java
+++ b/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/SessionBuilderSupplier.java
@@ -18,6 +18,7 @@
*/
package org.eclipse.aether.supplier;
+import java.util.Arrays;
import java.util.function.Supplier;
import org.eclipse.aether.RepositorySystem;
@@ -29,13 +30,14 @@ import org.eclipse.aether.collection.DependencyGraphTransformer;
import org.eclipse.aether.collection.DependencyManager;
import org.eclipse.aether.collection.DependencySelector;
import org.eclipse.aether.collection.DependencyTraverser;
+import org.eclipse.aether.internal.impl.scope.OptionalDependencySelector;
+import org.eclipse.aether.internal.impl.scope.ScopeDependencySelector;
import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
import org.eclipse.aether.util.artifact.DefaultArtifactTypeRegistry;
+import org.eclipse.aether.util.artifact.JavaScopes;
import org.eclipse.aether.util.graph.manager.ClassicDependencyManager;
import org.eclipse.aether.util.graph.selector.AndDependencySelector;
import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector;
-import org.eclipse.aether.util.graph.selector.OptionalDependencySelector;
-import org.eclipse.aether.util.graph.selector.ScopeDependencySelector;
import org.eclipse.aether.util.graph.transformer.ChainedDependencyGraphTransformer;
import org.eclipse.aether.util.graph.transformer.ConflictResolver;
import org.eclipse.aether.util.graph.transformer.JavaDependencyContextRefiner;
@@ -54,15 +56,11 @@ import static java.util.Objects.requireNonNull;
* of sessions, use {@link CloseableSession#close()} method on built instance(s).
* <p>
* Extend this class and override methods to customize, if needed.
+ * <p>
+ * Resolver created as this is NOT using {@link org.eclipse.aether.scope.ScopeManager}!
*
* @since 2.0.0
- *
- * @deprecated (To be removed as it was introduced in 2.0.0-alpha-2!) This class is wrong, as it uses Resolver 1.x
- * bits that do interpret dependency scopes. The proper session supplier should be provided by consumer project
- * (Maven) that also defines the dependency scopes and their meaning and semantics, as session need to be equipped
- * with these bits. Session is very much dependent on the consumer project.
*/
-@Deprecated
public class SessionBuilderSupplier implements Supplier<SessionBuilder> {
protected final RepositorySystem repositorySystem;
@@ -84,13 +82,13 @@ public class SessionBuilderSupplier implements Supplier<SessionBuilder> {
}
protected DependencyManager getDependencyManager() {
- return new ClassicDependencyManager();
+ return new ClassicDependencyManager(false, null);
}
protected DependencySelector getDependencySelector() {
return new AndDependencySelector(
- new ScopeDependencySelector("test", "provided"),
- new OptionalDependencySelector(),
+ ScopeDependencySelector.legacy(null, Arrays.asList(JavaScopes.TEST, JavaScopes.PROVIDED)),
+ OptionalDependencySelector.fromDirect(),
new ExclusionDependencySelector());
}
diff --git a/maven-resolver-supplier/src/test/java/org/eclipse/aether/supplier/RepositorySystemSupplierTest.java b/maven-resolver-supplier-mvn3/src/test/java/org/eclipse/aether/supplier/RepositorySystemSupplierTest.java
similarity index 100%
copy from maven-resolver-supplier/src/test/java/org/eclipse/aether/supplier/RepositorySystemSupplierTest.java
copy to maven-resolver-supplier-mvn3/src/test/java/org/eclipse/aether/supplier/RepositorySystemSupplierTest.java
diff --git a/maven-resolver-supplier/pom.xml b/maven-resolver-supplier-mvn4/pom.xml
similarity index 95%
rename from maven-resolver-supplier/pom.xml
rename to maven-resolver-supplier-mvn4/pom.xml
index 81de91f2..015c9514 100644
--- a/maven-resolver-supplier/pom.xml
+++ b/maven-resolver-supplier-mvn4/pom.xml
@@ -26,12 +26,14 @@
<version>2.0.0-SNAPSHOT</version>
</parent>
- <artifactId>maven-resolver-supplier</artifactId>
+ <artifactId>maven-resolver-supplier-mvn4</artifactId>
- <name>Maven Artifact Resolver Instance Supplier</name>
+ <name>Maven Artifact Resolver Instance Supplier Maven4</name>
<description>A helper module to provide RepositorySystem instances.</description>
<properties>
+ <javaVersion>17</javaVersion>
+
<Automatic-Module-Name>org.apache.maven.resolver.supplier</Automatic-Module-Name>
<Bundle-SymbolicName>${Automatic-Module-Name}</Bundle-SymbolicName>
</properties>
@@ -73,7 +75,7 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
- <version>${mavenVersion}</version>
+ <version>${maven4Version}</version>
<exclusions>
<exclusion>
<groupId>javax.inject</groupId>
@@ -96,7 +98,7 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model-builder</artifactId>
- <version>${mavenVersion}</version>
+ <version>${maven4Version}</version>
<exclusions>
<exclusion>
<groupId>javax.inject</groupId>
diff --git a/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/SystemScopeHandler.java b/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/SystemScopeHandler.java
new file mode 100644
index 00000000..58741e2e
--- /dev/null
+++ b/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/SystemScopeHandler.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether;
+
+/**
+ * This class here is merely to provide backward compatibility to Maven4-alpha-13. Pretend is not here.
+ *
+ * @since 2.0.0
+ */
+@Deprecated
+public interface SystemScopeHandler {}
diff --git a/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/Maven4ScopeManagerConfiguration.java b/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/Maven4ScopeManagerConfiguration.java
new file mode 100644
index 00000000..2b5fa044
--- /dev/null
+++ b/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/Maven4ScopeManagerConfiguration.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.supplier;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.stream.Collectors;
+
+import org.eclipse.aether.artifact.ArtifactProperties;
+import org.eclipse.aether.impl.scope.BuildScopeMatrixSource;
+import org.eclipse.aether.impl.scope.BuildScopeSource;
+import org.eclipse.aether.impl.scope.CommonBuilds;
+import org.eclipse.aether.impl.scope.InternalScopeManager;
+import org.eclipse.aether.impl.scope.ScopeManagerConfiguration;
+import org.eclipse.aether.internal.impl.scope.ScopeManagerDump;
+import org.eclipse.aether.scope.DependencyScope;
+import org.eclipse.aether.scope.ResolutionScope;
+
+import static org.eclipse.aether.impl.scope.BuildScopeQuery.all;
+import static org.eclipse.aether.impl.scope.BuildScopeQuery.byBuildPath;
+import static org.eclipse.aether.impl.scope.BuildScopeQuery.byProjectPath;
+import static org.eclipse.aether.impl.scope.BuildScopeQuery.select;
+import static org.eclipse.aether.impl.scope.BuildScopeQuery.singleton;
+import static org.eclipse.aether.impl.scope.BuildScopeQuery.union;
+
+/**
+ * Maven4 scope configurations. Configures scope manager to support Maven4 scopes.
+ *
+ * @since 2.0.0
+ */
+public final class Maven4ScopeManagerConfiguration implements ScopeManagerConfiguration {
+ public static final Maven4ScopeManagerConfiguration INSTANCE = new Maven4ScopeManagerConfiguration();
+
+ public static final String DS_NONE = "none";
+ public static final String DS_COMPILE = "compile";
+ public static final String DS_COMPILE_ONLY = "compileOnly";
+ public static final String DS_RUNTIME = "runtime";
+ public static final String DS_PROVIDED = "provided";
+ public static final String DS_SYSTEM = "system";
+ public static final String DS_TEST = "test";
+ public static final String DS_TEST_RUNTIME = "testRuntime";
+ public static final String DS_TEST_ONLY = "testOnly";
+ public static final String RS_NONE = "none";
+ public static final String RS_MAIN_COMPILE = "main-compile";
+ public static final String RS_MAIN_COMPILE_PLUS_RUNTIME = "main-compilePlusRuntime";
+ public static final String RS_MAIN_RUNTIME = "main-runtime";
+ public static final String RS_MAIN_RUNTIME_PLUS_SYSTEM = "main-runtimePlusSystem";
+ public static final String RS_TEST_COMPILE = "test-compile";
+ public static final String RS_TEST_RUNTIME = "test-runtime";
+
+ private Maven4ScopeManagerConfiguration() {}
+
+ @Override
+ public String getId() {
+ return "Maven4";
+ }
+
+ @Override
+ public boolean isStrictDependencyScopes() {
+ return false;
+ }
+
+ @Override
+ public boolean isStrictResolutionScopes() {
+ return false;
+ }
+
+ @Override
+ public BuildScopeSource getBuildScopeSource() {
+ return new BuildScopeMatrixSource(
+ Arrays.asList(CommonBuilds.PROJECT_PATH_MAIN, CommonBuilds.PROJECT_PATH_TEST),
+ Arrays.asList(CommonBuilds.BUILD_PATH_COMPILE, CommonBuilds.BUILD_PATH_RUNTIME));
+ }
+
+ @Override
+ public Collection<DependencyScope> buildDependencyScopes(InternalScopeManager internalScopeManager) {
+ ArrayList<DependencyScope> result = new ArrayList<>();
+ result.add(internalScopeManager.createDependencyScope(DS_COMPILE, true, all()));
+ result.add(internalScopeManager.createDependencyScope(
+ DS_RUNTIME, true, byBuildPath(CommonBuilds.BUILD_PATH_RUNTIME)));
+ result.add(internalScopeManager.createDependencyScope(
+ DS_PROVIDED,
+ false,
+ union(
+ byBuildPath(CommonBuilds.BUILD_PATH_COMPILE),
+ select(CommonBuilds.PROJECT_PATH_TEST, CommonBuilds.BUILD_PATH_RUNTIME))));
+ result.add(internalScopeManager.createDependencyScope(
+ DS_TEST, false, byProjectPath(CommonBuilds.PROJECT_PATH_TEST)));
+ result.add(internalScopeManager.createSystemDependencyScope(
+ DS_SYSTEM, false, all(), ArtifactProperties.LOCAL_PATH));
+ result.add(internalScopeManager.createDependencyScope(DS_NONE, false, Collections.emptySet()));
+ result.add(internalScopeManager.createDependencyScope(
+ DS_COMPILE_ONLY, false, singleton(CommonBuilds.PROJECT_PATH_MAIN, CommonBuilds.BUILD_PATH_COMPILE)));
+ result.add(internalScopeManager.createDependencyScope(
+ DS_TEST_RUNTIME, false, singleton(CommonBuilds.PROJECT_PATH_TEST, CommonBuilds.BUILD_PATH_RUNTIME)));
+ result.add(internalScopeManager.createDependencyScope(
+ DS_TEST_ONLY, false, singleton(CommonBuilds.PROJECT_PATH_TEST, CommonBuilds.BUILD_PATH_COMPILE)));
+ return result;
+ }
+
+ @Override
+ public Collection<ResolutionScope> buildResolutionScopes(InternalScopeManager internalScopeManager) {
+ Collection<DependencyScope> allDependencyScopes = internalScopeManager.getDependencyScopeUniverse();
+ Collection<DependencyScope> nonTransitiveDependencyScopes =
+ allDependencyScopes.stream().filter(s -> !s.isTransitive()).collect(Collectors.toSet());
+ DependencyScope system =
+ internalScopeManager.getDependencyScope(DS_SYSTEM).orElse(null);
+
+ ArrayList<ResolutionScope> result = new ArrayList<>();
+ result.add(internalScopeManager.createResolutionScope(
+ RS_NONE,
+ InternalScopeManager.Mode.REMOVE,
+ Collections.emptySet(),
+ Collections.emptySet(),
+ allDependencyScopes));
+ result.add(internalScopeManager.createResolutionScope(
+ RS_MAIN_COMPILE,
+ InternalScopeManager.Mode.ELIMINATE,
+ singleton(CommonBuilds.PROJECT_PATH_MAIN, CommonBuilds.BUILD_PATH_COMPILE),
+ Collections.singletonList(system),
+ nonTransitiveDependencyScopes));
+ result.add(internalScopeManager.createResolutionScope(
+ RS_MAIN_COMPILE_PLUS_RUNTIME,
+ InternalScopeManager.Mode.ELIMINATE,
+ byProjectPath(CommonBuilds.PROJECT_PATH_MAIN),
+ Collections.singletonList(system),
+ nonTransitiveDependencyScopes));
+ result.add(internalScopeManager.createResolutionScope(
+ RS_MAIN_RUNTIME,
+ InternalScopeManager.Mode.REMOVE,
+ singleton(CommonBuilds.PROJECT_PATH_MAIN, CommonBuilds.BUILD_PATH_RUNTIME),
+ Collections.emptySet(),
+ nonTransitiveDependencyScopes));
+ result.add(internalScopeManager.createResolutionScope(
+ RS_MAIN_RUNTIME_PLUS_SYSTEM,
+ InternalScopeManager.Mode.REMOVE,
+ singleton(CommonBuilds.PROJECT_PATH_MAIN, CommonBuilds.BUILD_PATH_RUNTIME),
+ Collections.singletonList(system),
+ nonTransitiveDependencyScopes));
+ result.add(internalScopeManager.createResolutionScope(
+ RS_TEST_COMPILE,
+ InternalScopeManager.Mode.ELIMINATE,
+ select(CommonBuilds.PROJECT_PATH_TEST, CommonBuilds.BUILD_PATH_COMPILE),
+ Collections.singletonList(system),
+ nonTransitiveDependencyScopes));
+ result.add(internalScopeManager.createResolutionScope(
+ RS_TEST_RUNTIME,
+ InternalScopeManager.Mode.ELIMINATE,
+ select(CommonBuilds.PROJECT_PATH_TEST, CommonBuilds.BUILD_PATH_RUNTIME),
+ Collections.singletonList(system),
+ nonTransitiveDependencyScopes));
+ return result;
+ }
+
+ // ===
+
+ public static void main(String... args) {
+ ScopeManagerDump.dump(Maven4ScopeManagerConfiguration.INSTANCE);
+ }
+}
diff --git a/maven-resolver-supplier/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java b/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
similarity index 100%
rename from maven-resolver-supplier/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
rename to maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java
diff --git a/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/SessionBuilderSupplier.java b/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/SessionBuilderSupplier.java
new file mode 100644
index 00000000..31e0f79d
--- /dev/null
+++ b/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/SessionBuilderSupplier.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.supplier;
+
+import java.util.function.Supplier;
+
+import org.apache.maven.repository.internal.MavenSessionBuilderSupplier;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession.CloseableSession;
+import org.eclipse.aether.RepositorySystemSession.SessionBuilder;
+import org.eclipse.aether.collection.DependencyManager;
+import org.eclipse.aether.impl.scope.InternalScopeManager;
+import org.eclipse.aether.internal.impl.scope.ScopeManagerImpl;
+import org.eclipse.aether.util.graph.manager.ClassicDependencyManager;
+
+/**
+ * A simple {@link Supplier} of {@link SessionBuilder} instances, that on each call supplies newly
+ * constructed instance. To create session out of builder, use {@link SessionBuilder#build()}. For proper closing
+ * of sessions, use {@link CloseableSession#close()} method on built instance(s).
+ * <p>
+ * Extend this class and override methods to customize, if needed.
+ *
+ * @since 2.0.0
+ */
+public class SessionBuilderSupplier extends MavenSessionBuilderSupplier {
+ public SessionBuilderSupplier(RepositorySystem repositorySystem) {
+ super(repositorySystem);
+ }
+
+ @Override
+ protected void configureSessionBuilder(SessionBuilder session) {
+ super.configureSessionBuilder(session);
+ session.setScopeManager(getScopeManager());
+ }
+
+ @Override
+ protected DependencyManager getDependencyManager() {
+ return new ClassicDependencyManager(true, getScopeManager()); // same default as in Maven4
+ }
+
+ protected InternalScopeManager getScopeManager() {
+ return new ScopeManagerImpl(Maven4ScopeManagerConfiguration.INSTANCE);
+ }
+}
diff --git a/maven-resolver-supplier/src/test/java/org/eclipse/aether/supplier/RepositorySystemSupplierTest.java b/maven-resolver-supplier-mvn4/src/test/java/org/eclipse/aether/supplier/RepositorySystemSupplierTest.java
similarity index 100%
rename from maven-resolver-supplier/src/test/java/org/eclipse/aether/supplier/RepositorySystemSupplierTest.java
rename to maven-resolver-supplier-mvn4/src/test/java/org/eclipse/aether/supplier/RepositorySystemSupplierTest.java
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java
index ff001622..7a980f35 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java
@@ -20,13 +20,14 @@ package org.eclipse.aether.util.graph.manager;
import java.util.*;
-import org.eclipse.aether.SystemScopeHandler;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.collection.DependencyCollectionContext;
import org.eclipse.aether.collection.DependencyManagement;
import org.eclipse.aether.collection.DependencyManager;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.Exclusion;
+import org.eclipse.aether.scope.ScopeManager;
+import org.eclipse.aether.scope.SystemDependencyScope;
import static java.util.Objects.requireNonNull;
@@ -36,13 +37,6 @@ import static java.util.Objects.requireNonNull;
* @since 2.0.0
*/
public abstract class AbstractDependencyManager implements DependencyManager {
- /**
- * This predicate is here ONLY to support deprecated constructors.
- *
- * @deprecated To be removed when deprecated constructors are removed.
- */
- @Deprecated
- protected static final SystemScopeHandler SYSTEM_SCOPE_HANDLER = SystemScopeHandler.LEGACY;
protected final int depth;
@@ -60,11 +54,11 @@ public abstract class AbstractDependencyManager implements DependencyManager {
protected final Map<Object, Collection<Exclusion>> managedExclusions;
- protected final SystemScopeHandler systemScopeHandler;
+ protected final SystemDependencyScope systemDependencyScope;
private final int hashCode;
- protected AbstractDependencyManager(int deriveUntil, int applyFrom, SystemScopeHandler systemScopeHandler) {
+ protected AbstractDependencyManager(int deriveUntil, int applyFrom, ScopeManager scopeManager) {
this(
0,
deriveUntil,
@@ -74,7 +68,7 @@ public abstract class AbstractDependencyManager implements DependencyManager {
Collections.emptyMap(),
Collections.emptyMap(),
Collections.emptyMap(),
- systemScopeHandler);
+ scopeManager != null ? scopeManager.getSystemScope().orElse(null) : SystemDependencyScope.LEGACY);
}
@SuppressWarnings("checkstyle:ParameterNumber")
@@ -87,7 +81,7 @@ public abstract class AbstractDependencyManager implements DependencyManager {
Map<Object, Boolean> managedOptionals,
Map<Object, String> managedLocalPaths,
Map<Object, Collection<Exclusion>> managedExclusions,
- SystemScopeHandler systemScopeHandler) {
+ SystemDependencyScope systemDependencyScope) {
this.depth = depth;
this.deriveUntil = deriveUntil;
this.applyFrom = applyFrom;
@@ -96,7 +90,8 @@ public abstract class AbstractDependencyManager implements DependencyManager {
this.managedOptionals = requireNonNull(managedOptionals);
this.managedLocalPaths = requireNonNull(managedLocalPaths);
this.managedExclusions = requireNonNull(managedExclusions);
- this.systemScopeHandler = requireNonNull(systemScopeHandler);
+ // nullable: if using scope manager, but there is no system scope defined
+ this.systemDependencyScope = systemDependencyScope;
this.hashCode = Objects.hash(
depth,
@@ -157,7 +152,9 @@ public abstract class AbstractDependencyManager implements DependencyManager {
managedOptionals.put(key, optional);
}
- String localPath = systemScopeHandler.getSystemPath(managedDependency.getArtifact());
+ String localPath = systemDependencyScope == null
+ ? null
+ : systemDependencyScope.getSystemPath(managedDependency.getArtifact());
if (localPath != null && !managedLocalPaths.containsKey(key)) {
if (managedLocalPaths == this.managedLocalPaths) {
managedLocalPaths = new HashMap<>(this.managedLocalPaths);
@@ -198,17 +195,19 @@ public abstract class AbstractDependencyManager implements DependencyManager {
}
management.setScope(scope);
- if (!systemScopeHandler.isSystemScope(scope)
- && systemScopeHandler.getSystemPath(dependency.getArtifact()) != null) {
+ if (systemDependencyScope != null
+ && !systemDependencyScope.is(scope)
+ && systemDependencyScope.getSystemPath(dependency.getArtifact()) != null) {
Map<String, String> properties =
new HashMap<>(dependency.getArtifact().getProperties());
- systemScopeHandler.setSystemPath(properties, null);
+ systemDependencyScope.setSystemPath(properties, null);
management.setProperties(properties);
}
}
- if ((systemScopeHandler.isSystemScope(scope))
- || (scope == null && systemScopeHandler.isSystemScope(dependency.getScope()))) {
+ if (systemDependencyScope != null
+ && (systemDependencyScope.is(scope)
+ || (scope == null && systemDependencyScope.is(dependency.getScope())))) {
String localPath = managedLocalPaths.get(key);
if (localPath != null) {
if (management == null) {
@@ -216,7 +215,7 @@ public abstract class AbstractDependencyManager implements DependencyManager {
}
Map<String, String> properties =
new HashMap<>(dependency.getArtifact().getProperties());
- systemScopeHandler.setSystemPath(properties, localPath);
+ systemDependencyScope.setSystemPath(properties, localPath);
management.setProperties(properties);
}
}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/ClassicDependencyManager.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/ClassicDependencyManager.java
index 148e3872..697c93bb 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/ClassicDependencyManager.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/ClassicDependencyManager.java
@@ -21,10 +21,11 @@ package org.eclipse.aether.util.graph.manager;
import java.util.Collection;
import java.util.Map;
-import org.eclipse.aether.SystemScopeHandler;
import org.eclipse.aether.collection.DependencyCollectionContext;
import org.eclipse.aether.collection.DependencyManager;
import org.eclipse.aether.graph.Exclusion;
+import org.eclipse.aether.scope.ScopeManager;
+import org.eclipse.aether.scope.SystemDependencyScope;
/**
* A dependency manager that mimics the way Maven 2.x works. This manager was used throughout all Maven 3.x versions.
@@ -39,11 +40,11 @@ public final class ClassicDependencyManager extends AbstractDependencyManager {
*/
@Deprecated
public ClassicDependencyManager() {
- this(SYSTEM_SCOPE_HANDLER);
+ this(null);
}
- public ClassicDependencyManager(SystemScopeHandler systemScopeHandler) {
- this(false, systemScopeHandler);
+ public ClassicDependencyManager(ScopeManager scopeManager) {
+ this(false, scopeManager);
}
/**
@@ -55,8 +56,8 @@ public final class ClassicDependencyManager extends AbstractDependencyManager {
*
* @since 2.0.0
*/
- public ClassicDependencyManager(boolean transitive, SystemScopeHandler systemScopeHandler) {
- super(transitive ? Integer.MAX_VALUE : 2, 2, systemScopeHandler);
+ public ClassicDependencyManager(boolean transitive, ScopeManager scopeManager) {
+ super(transitive ? Integer.MAX_VALUE : 2, 2, scopeManager);
}
@SuppressWarnings("checkstyle:ParameterNumber")
@@ -69,7 +70,7 @@ public final class ClassicDependencyManager extends AbstractDependencyManager {
Map<Object, Boolean> managedOptionals,
Map<Object, String> managedLocalPaths,
Map<Object, Collection<Exclusion>> managedExclusions,
- SystemScopeHandler systemScopeHandler) {
+ SystemDependencyScope systemDependencyScope) {
super(
depth,
deriveUntil,
@@ -79,7 +80,7 @@ public final class ClassicDependencyManager extends AbstractDependencyManager {
managedOptionals,
managedLocalPaths,
managedExclusions,
- systemScopeHandler);
+ systemDependencyScope);
}
@Override
@@ -109,6 +110,6 @@ public final class ClassicDependencyManager extends AbstractDependencyManager {
managedOptionals,
managedLocalPaths,
managedExclusions,
- systemScopeHandler);
+ systemDependencyScope);
}
}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/DefaultDependencyManager.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/DefaultDependencyManager.java
index e8de2be3..aeee7f0b 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/DefaultDependencyManager.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/DefaultDependencyManager.java
@@ -21,9 +21,10 @@ package org.eclipse.aether.util.graph.manager;
import java.util.Collection;
import java.util.Map;
-import org.eclipse.aether.SystemScopeHandler;
import org.eclipse.aether.collection.DependencyManager;
import org.eclipse.aether.graph.Exclusion;
+import org.eclipse.aether.scope.ScopeManager;
+import org.eclipse.aether.scope.SystemDependencyScope;
/**
* A dependency manager managing dependencies on all levels supporting transitive dependency management.
@@ -45,11 +46,11 @@ public final class DefaultDependencyManager extends AbstractDependencyManager {
*/
@Deprecated
public DefaultDependencyManager() {
- this(SYSTEM_SCOPE_HANDLER);
+ this(null);
}
- public DefaultDependencyManager(SystemScopeHandler systemScopeHandler) {
- super(Integer.MAX_VALUE, 0, systemScopeHandler);
+ public DefaultDependencyManager(ScopeManager scopeManager) {
+ super(Integer.MAX_VALUE, 0, scopeManager);
}
@SuppressWarnings("checkstyle:ParameterNumber")
@@ -62,7 +63,7 @@ public final class DefaultDependencyManager extends AbstractDependencyManager {
Map<Object, Boolean> managedOptionals,
Map<Object, String> managedLocalPaths,
Map<Object, Collection<Exclusion>> managedExclusions,
- SystemScopeHandler systemScopeHandler) {
+ SystemDependencyScope systemDependencyScope) {
super(
depth,
deriveUntil,
@@ -72,7 +73,7 @@ public final class DefaultDependencyManager extends AbstractDependencyManager {
managedOptionals,
managedLocalPaths,
managedExclusions,
- systemScopeHandler);
+ systemDependencyScope);
}
@Override
@@ -91,6 +92,6 @@ public final class DefaultDependencyManager extends AbstractDependencyManager {
managedOptionals,
managedLocalPaths,
managedExclusions,
- systemScopeHandler);
+ systemDependencyScope);
}
}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/TransitiveDependencyManager.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/TransitiveDependencyManager.java
index 5304615f..bac84476 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/TransitiveDependencyManager.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/TransitiveDependencyManager.java
@@ -21,9 +21,10 @@ package org.eclipse.aether.util.graph.manager;
import java.util.Collection;
import java.util.Map;
-import org.eclipse.aether.SystemScopeHandler;
import org.eclipse.aether.collection.DependencyManager;
import org.eclipse.aether.graph.Exclusion;
+import org.eclipse.aether.scope.ScopeManager;
+import org.eclipse.aether.scope.SystemDependencyScope;
/**
* A dependency manager managing transitive dependencies supporting transitive dependency management.
@@ -42,11 +43,11 @@ public final class TransitiveDependencyManager extends AbstractDependencyManager
*/
@Deprecated
public TransitiveDependencyManager() {
- this(SYSTEM_SCOPE_HANDLER);
+ this(null);
}
- public TransitiveDependencyManager(SystemScopeHandler systemScopeHandler) {
- super(Integer.MAX_VALUE, 2, systemScopeHandler);
+ public TransitiveDependencyManager(ScopeManager scopeManager) {
+ super(Integer.MAX_VALUE, 2, scopeManager);
}
@SuppressWarnings("checkstyle:ParameterNumber")
@@ -59,7 +60,7 @@ public final class TransitiveDependencyManager extends AbstractDependencyManager
Map<Object, Boolean> managedOptionals,
Map<Object, String> managedLocalPaths,
Map<Object, Collection<Exclusion>> managedExclusions,
- SystemScopeHandler systemScopeHandler) {
+ SystemDependencyScope systemDependencyScope) {
super(
depth,
deriveUntil,
@@ -69,7 +70,7 @@ public final class TransitiveDependencyManager extends AbstractDependencyManager
managedOptionals,
managedLocalPaths,
managedExclusions,
- systemScopeHandler);
+ systemDependencyScope);
}
@Override
@@ -88,6 +89,6 @@ public final class TransitiveDependencyManager extends AbstractDependencyManager
managedOptionals,
managedLocalPaths,
managedExclusions,
- systemScopeHandler);
+ systemDependencyScope);
}
}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/OptionalDependencySelector.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/OptionalDependencySelector.java
index 64c5abfc..d59c3ea0 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/OptionalDependencySelector.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/OptionalDependencySelector.java
@@ -28,7 +28,10 @@ import static java.util.Objects.requireNonNull;
* A dependency selector that excludes optional dependencies which occur beyond level one of the dependency graph.
*
* @see Dependency#isOptional()
+ * @see org.eclipse.aether.internal.impl.scope.OptionalDependencySelector
+ * @deprecated This class is deprecated.
*/
+@Deprecated
public final class OptionalDependencySelector implements DependencySelector {
private final int depth;
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java
index adcb60ef..398efa3c 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java
@@ -37,7 +37,10 @@ import static java.util.Objects.requireNonNull;
* In particular, the filter is not aware of scopes that logically include other scopes.
*
* @see Dependency#getScope()
+ * @see org.eclipse.aether.internal.impl.scope.ScopeDependencySelector
+ * @deprecated This class is deprecated.
*/
+@Deprecated
public final class ScopeDependencySelector implements DependencySelector {
private final boolean transitive;
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/manager/DependencyManagerTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/manager/DependencyManagerTest.java
index 6f5f4b24..130ac5c3 100644
--- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/manager/DependencyManagerTest.java
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/manager/DependencyManagerTest.java
@@ -22,7 +22,6 @@ import java.util.Arrays;
import java.util.Collections;
import org.eclipse.aether.RepositorySystemSession;
-import org.eclipse.aether.SystemScopeHandler;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.DependencyCollectionContext;
@@ -41,8 +40,6 @@ import static org.junit.jupiter.api.Assertions.*;
*/
public class DependencyManagerTest {
- private static final SystemScopeHandler SYSTEM_SCOPE_HANDLER = SystemScopeHandler.LEGACY;
-
private final Artifact A1 = new DefaultArtifact("test", "a", "", "1");
private final Artifact A2 = new DefaultArtifact("test", "a", "", "2");
@@ -76,7 +73,7 @@ public class DependencyManagerTest {
@Test
void testClassic() {
- DependencyManager manager = new ClassicDependencyManager(SYSTEM_SCOPE_HANDLER);
+ DependencyManager manager = new ClassicDependencyManager(null);
DependencyManagement mngt;
// depth=1: only exclusion applied, nothing more
@@ -135,7 +132,7 @@ public class DependencyManagerTest {
@Test
void testClassicTransitive() {
- DependencyManager manager = new ClassicDependencyManager(true, SYSTEM_SCOPE_HANDLER);
+ DependencyManager manager = new ClassicDependencyManager(true, null);
DependencyManagement mngt;
// depth=1: only exclusion applied, nothing more
@@ -195,7 +192,7 @@ public class DependencyManagerTest {
@Test
void testTransitive() {
- DependencyManager manager = new TransitiveDependencyManager(SYSTEM_SCOPE_HANDLER);
+ DependencyManager manager = new TransitiveDependencyManager(null);
DependencyManagement mngt;
// depth=1: only exclusion applied, nothing more
@@ -255,7 +252,7 @@ public class DependencyManagerTest {
@Test
void testDefault() {
- DependencyManager manager = new DefaultDependencyManager(SYSTEM_SCOPE_HANDLER);
+ DependencyManager manager = new DefaultDependencyManager(null);
DependencyManagement mngt;
// depth=1: all applied
diff --git a/pom.xml b/pom.xml
index 21474ae5..1d634b61 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,8 @@
<module>maven-resolver-transport-apache</module>
<module>maven-resolver-transport-wagon</module>
<module>maven-resolver-generator-gnupg</module>
- <module>maven-resolver-supplier</module>
+ <module>maven-resolver-supplier-mvn3</module>
+ <module>maven-resolver-supplier-mvn4</module>
<module>maven-resolver-demos</module>
<module>maven-resolver-tools</module>
</modules>
@@ -103,7 +104,8 @@
<!-- Used by Jetty Transport (client) and Test HTTP (server) -->
<jettyVersion>10.0.20</jettyVersion>
<!-- used by supplier and demo only -->
- <mavenVersion>4.0.0-alpha-12</mavenVersion>
+ <maven3Version>3.9.6</maven3Version>
+ <maven4Version>4.0.0-alpha-13</maven4Version>
<minimalMavenBuildVersion>[3.8.8,)</minimalMavenBuildVersion>
<!-- MRESOLVER-422: keep this in sync with Javadoc plugin configuration (but cannot directly, as this below is range) -->
<minimalJavaBuildVersion>[21,)</minimalJavaBuildVersion>
@@ -181,7 +183,12 @@
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
- <artifactId>maven-resolver-supplier</artifactId>
+ <artifactId>maven-resolver-supplier-mvn3</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.resolver</groupId>
+ <artifactId>maven-resolver-supplier-mvn4</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>