diff --git a/.github/workflows/maven-verify.yml b/.github/workflows/maven-verify.yml index dbdabb6f1..be6eeb616 100644 --- a/.github/workflows/maven-verify.yml +++ b/.github/workflows/maven-verify.yml @@ -27,5 +27,5 @@ jobs: uses: apache/maven-gh-actions-shared/.github/workflows/maven-verify.yml@v3 with: ff-site-run: false - + jdk-matrix: '[ "11", "17", "21" ]' diff --git a/Jenkinsfile b/Jenkinsfile index d89f893d1..ef5393dda 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -17,7 +17,5 @@ * under the License. */ -// Currently we can only build with JDK8+ based on the usage -// of bnd-maven-plugin. -asfMavenTlpStdBuild( 'jdks' : [ "8", "11", "17" ] ) +asfMavenTlpStdBuild( 'jdks' : [ "11", "17", "21" ] ) diff --git a/maven-resolver-api/pom.xml b/maven-resolver-api/pom.xml index 691aeb33d..c3a9991c0 100644 --- a/maven-resolver-api/pom.xml +++ b/maven-resolver-api/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-api 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 a1a2083e1..4583b065c 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 @@ -87,6 +87,11 @@ public String getUpdatePolicy() { return getSession().getUpdatePolicy(); } + @Override + public String getMetadataUpdatePolicy() { + return getSession().getMetadataUpdatePolicy(); + } + @Override public LocalRepository getLocalRepository() { return getSession().getLocalRepository(); diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java b/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java index 77303c7a7..0df38e759 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java @@ -146,6 +146,60 @@ public final class ConfigurationProperties { */ public static final int DEFAULT_HTTP_RETRY_HANDLER_COUNT = 3; + /** + * The initial retry interval of request to a remote server should be waited in case of "too many requests" + * (HTTP codes 429 and 503). Accepts long as milliseconds. This value is used if remote server does not use + * {@code Retry-After} header, in which case Server value is obeyed. + * + * @see #DEFAULT_HTTP_RETRY_HANDLER_INTERVAL + * @since 1.9.16 + */ + public static final String HTTP_RETRY_HANDLER_INTERVAL = PREFIX_CONNECTOR + "http.retryHandler.interval"; + + /** + * The default initial retry interval to use if {@link #HTTP_RETRY_HANDLER_INTERVAL} isn't set. + * Default value 5000ms. + * + * @since 1.9.16 + */ + public static final long DEFAULT_HTTP_RETRY_HANDLER_INTERVAL = 5000L; + + /** + * The maximum retry interval of request to a remote server above which the request should be aborted instead. + * In theory, a malicious server could tell Maven "come back after 100 years" that would stall the build for + * some. Using this parameter Maven will fail the request instead, if interval is above this value. + * + * @see #DEFAULT_HTTP_RETRY_HANDLER_INTERVAL_MAX + * @since 1.9.16 + */ + public static final String HTTP_RETRY_HANDLER_INTERVAL_MAX = PREFIX_CONNECTOR + "http.retryHandler.intervalMax"; + + /** + * The default retry interval maximum to use if {@link #HTTP_RETRY_HANDLER_INTERVAL_MAX} isn't set. + * Default value 5 minutes. + * + * @since 1.9.16 + */ + public static final long DEFAULT_HTTP_RETRY_HANDLER_INTERVAL_MAX = 300_000L; + + /** + * The HTTP codes of remote server responses that should be handled as "too many requests" + * (examples: HTTP codes 429 and 503). Accepts comma separated list of HTTP response codes. + * + * @see #DEFAULT_HTTP_RETRY_HANDLER_SERVICE_UNAVAILABLE + * @since 1.9.16 + */ + public static final String HTTP_RETRY_HANDLER_SERVICE_UNAVAILABLE = + PREFIX_CONNECTOR + "http.retryHandler.serviceUnavailable"; + + /** + * The default HTTP codes of remote server responses that should be handled as "too many requests". + * Default value: "429,503". + * + * @since 1.9.16 + */ + public static final String DEFAULT_HTTP_RETRY_HANDLER_SERVICE_UNAVAILABLE = "429,503"; + /** * Should HTTP client use preemptive auth (w/ BASIC) or not? * 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 a6e24fd57..9738d9a07 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 @@ -73,6 +73,8 @@ public final class DefaultRepositorySystemSession implements RepositorySystemSes private String updatePolicy; + private String metadataUpdatePolicy; + private LocalRepositoryManager localRepositoryManager; private FileTransformerManager fileTransformerManager; @@ -154,6 +156,7 @@ public DefaultRepositorySystemSession(RepositorySystemSession session) { setArtifactDescriptorPolicy(session.getArtifactDescriptorPolicy()); setChecksumPolicy(session.getChecksumPolicy()); setUpdatePolicy(session.getUpdatePolicy()); + setMetadataUpdatePolicy(session.getMetadataUpdatePolicy()); setLocalRepositoryManager(session.getLocalRepositoryManager()); setWorkspaceReader(session.getWorkspaceReader()); setRepositoryListener(session.getRepositoryListener()); @@ -293,6 +296,28 @@ public DefaultRepositorySystemSession setUpdatePolicy(String updatePolicy) { return this; } + @Override + public String getMetadataUpdatePolicy() { + return metadataUpdatePolicy; + } + + /** + * Sets the global metadata update policy. If set, the global update policy overrides the update policies of the remote + * repositories being used for resolution. + * + * @param metadataUpdatePolicy The global update policy, may be {@code null}/empty to apply the per-repository policies. + * @return This session for chaining, never {@code null}. + * @see RepositoryPolicy#UPDATE_POLICY_ALWAYS + * @see RepositoryPolicy#UPDATE_POLICY_DAILY + * @see RepositoryPolicy#UPDATE_POLICY_NEVER + * @since TBD + */ + public DefaultRepositorySystemSession setMetadataUpdatePolicy(String metadataUpdatePolicy) { + verifyStateForMutation(); + this.metadataUpdatePolicy = metadataUpdatePolicy; + return this; + } + @Override public LocalRepository getLocalRepository() { LocalRepositoryManager lrm = getLocalRepositoryManager(); 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 31e99cd70..581161119 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 @@ -94,7 +94,7 @@ public interface RepositorySystemSession { String getChecksumPolicy(); /** - * Gets the global update policy. If set, the global update policy overrides the update policies of the remote + * Gets the global data update policy. If set, the global update policy overrides the update policies of the remote * repositories being used for resolution. * * @return The global update policy or {@code null}/empty if not set and the per-repository policies apply. @@ -104,6 +104,18 @@ public interface RepositorySystemSession { */ String getUpdatePolicy(); + /** + * Gets the global metadata update policy. If set, the global update policy overrides the update policies of the remote + * repositories being used for resolution. + * + * @return The global update policy or {@code null}/empty if not set and the per-repository policies apply. + * @see RepositoryPolicy#UPDATE_POLICY_ALWAYS + * @see RepositoryPolicy#UPDATE_POLICY_DAILY + * @see RepositoryPolicy#UPDATE_POLICY_NEVER + * @since TBD + */ + String getMetadataUpdatePolicy(); + /** * Gets the local repository used during this session. This is a convenience method for * {@link LocalRepositoryManager#getRepository()}. diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/RepositoryPolicy.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/RepositoryPolicy.java index 14f44d44d..6adf28bf6 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/RepositoryPolicy.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/RepositoryPolicy.java @@ -62,13 +62,23 @@ public final class RepositoryPolicy { private final String updatePolicy; + private final String metadataUpdatePolicy; + private final String checksumPolicy; /** * Creates a new policy with checksum warnings and daily update checks. */ public RepositoryPolicy() { - this(true, UPDATE_POLICY_DAILY, CHECKSUM_POLICY_WARN); + this(true, UPDATE_POLICY_DAILY, UPDATE_POLICY_DAILY, CHECKSUM_POLICY_WARN); + } + + /** + * Creates a new policy with the specified settings (uses same update policy for data and metadata, retains old + * resolver behaviour). + */ + public RepositoryPolicy(boolean enabled, String updatePolicy, String checksumPolicy) { + this(enabled, updatePolicy, updatePolicy, checksumPolicy); } /** @@ -76,12 +86,16 @@ public RepositoryPolicy() { * * @param enabled A flag whether the associated repository should be accessed or not. * @param updatePolicy The update interval after which locally cached data from the repository is considered stale - * and should be refetched, may be {@code null}. + * and should be re-fetched, may be {@code null}. + * @param metadataUpdatePolicy The update interval after which locally cached metadata from the repository is considered stale + * and should be re-fetched, may be {@code null}. * @param checksumPolicy The way checksum verification should be handled, may be {@code null}. + * @since TBD */ - public RepositoryPolicy(boolean enabled, String updatePolicy, String checksumPolicy) { + public RepositoryPolicy(boolean enabled, String updatePolicy, String metadataUpdatePolicy, String checksumPolicy) { this.enabled = enabled; this.updatePolicy = (updatePolicy != null) ? updatePolicy : ""; + this.metadataUpdatePolicy = (metadataUpdatePolicy != null) ? metadataUpdatePolicy : ""; this.checksumPolicy = (checksumPolicy != null) ? checksumPolicy : ""; } @@ -103,6 +117,16 @@ public String getUpdatePolicy() { return updatePolicy; } + /** + * Gets the update policy for locally cached metadata from the repository. + * + * @return The update policy, never {@code null}. + * @since TBD + */ + public String getMetadataUpdatePolicy() { + return metadataUpdatePolicy; + } + /** * Gets the policy for checksum validation. * @@ -114,11 +138,10 @@ public String getChecksumPolicy() { @Override public String toString() { - StringBuilder buffer = new StringBuilder(256); - buffer.append("enabled=").append(isEnabled()); - buffer.append(", checksums=").append(getChecksumPolicy()); - buffer.append(", updates=").append(getUpdatePolicy()); - return buffer.toString(); + return "enabled=" + isEnabled() + + ", checksums=" + getChecksumPolicy() + + ", updates=" + getUpdatePolicy() + + ", metadataUpdates=" + getMetadataUpdatePolicy(); } @Override diff --git a/maven-resolver-connector-basic/pom.xml b/maven-resolver-connector-basic/pom.xml index 2f9333ebb..f7dff4654 100644 --- a/maven-resolver-connector-basic/pom.xml +++ b/maven-resolver-connector-basic/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-connector-basic diff --git a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnectorFactory.java b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnectorFactory.java index 8fa86edcb..15470d3e3 100644 --- a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnectorFactory.java +++ b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnectorFactory.java @@ -44,8 +44,9 @@ * {@link org.eclipse.aether.spi.connector.transport.TransporterFactory transporters} and * {@link org.eclipse.aether.spi.connector.layout.RepositoryLayoutFactory repository layouts} for the transfers. */ -@Named("basic") +@Named(BasicRepositoryConnectorFactory.NAME) public final class BasicRepositoryConnectorFactory implements RepositoryConnectorFactory, Service { + public static final String NAME = "basic"; private TransporterProvider transporterProvider; private RepositoryLayoutProvider layoutProvider; @@ -63,12 +64,13 @@ public final class BasicRepositoryConnectorFactory implements RepositoryConnecto * clients, the new factory needs to be configured via its various mutators before first use or runtime errors will * occur. */ + @Deprecated public BasicRepositoryConnectorFactory() { // enables default constructor } @Inject - BasicRepositoryConnectorFactory( + public BasicRepositoryConnectorFactory( TransporterProvider transporterProvider, RepositoryLayoutProvider layoutProvider, ChecksumPolicyProvider checksumPolicyProvider, 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 00406c549..620acbabd 100644 --- a/maven-resolver-demos/maven-resolver-demo-maven-plugin/pom.xml +++ b/maven-resolver-demos/maven-resolver-demo-maven-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver-demos - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT resolver-demo-maven-plugin @@ -33,7 +33,7 @@ A simple Maven plugin using Maven Artifact Resolver with Maven repositories. - ${mavenVersion} + ${minimalMavenBuildVersion} diff --git a/maven-resolver-demos/maven-resolver-demo-snippets/pom.xml b/maven-resolver-demos/maven-resolver-demo-snippets/pom.xml index 7364a4a92..bdc1dc2e8 100644 --- a/maven-resolver-demos/maven-resolver-demo-snippets/pom.xml +++ b/maven-resolver-demos/maven-resolver-demo-snippets/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver-demos - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-demo-snippets @@ -65,6 +65,10 @@ org.apache.maven.resolver maven-resolver-transport-http + + org.apache.maven.resolver + maven-resolver-supplier + org.apache.maven maven-resolver-provider diff --git a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/guice/DemoResolverModule.java b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/guice/DemoResolverModule.java index c382e7480..155d0ef51 100644 --- a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/guice/DemoResolverModule.java +++ b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/guice/DemoResolverModule.java @@ -32,8 +32,10 @@ import org.apache.maven.model.building.DefaultModelBuilderFactory; import org.apache.maven.model.building.ModelBuilder; 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.SnapshotMetadataGeneratorFactory; import org.apache.maven.repository.internal.VersionsMetadataGeneratorFactory; import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory; @@ -142,4 +144,9 @@ Set provideMetadataGeneratorFactories( ModelBuilder provideModelBuilder() { return new DefaultModelBuilderFactory().newInstance(); } + + @Provides + ModelCacheFactory provideModelCacheFactory() { + return new DefaultModelCacheFactory(); + } } diff --git a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/supplier/SupplierRepositorySystemFactory.java b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/supplier/SupplierRepositorySystemFactory.java new file mode 100644 index 000000000..a649322bd --- /dev/null +++ b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/supplier/SupplierRepositorySystemFactory.java @@ -0,0 +1,31 @@ +/* + * 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.apache.maven.resolver.examples.supplier; + +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.supplier.RepositorySystemSupplier; + +/** + * A factory for repository system instances that employs Maven Artifact Resolver's provided supplier. + */ +public class SupplierRepositorySystemFactory { + public static RepositorySystem newRepositorySystem() { + return new RepositorySystemSupplier().get(); + } +} diff --git a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/util/Booter.java b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/util/Booter.java index 2744650b6..e650786d6 100644 --- a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/util/Booter.java +++ b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/util/Booter.java @@ -36,6 +36,8 @@ public class Booter { public static final String SERVICE_LOCATOR = "serviceLocator"; + public static final String SUPPLIER = "supplier"; + public static final String GUICE = "guice"; public static final String SISU = "sisu"; @@ -44,7 +46,7 @@ public class Booter { public static String selectFactory(String[] args) { if (args == null || args.length == 0) { - return SERVICE_LOCATOR; + return SUPPLIER; } else { return args[0]; } @@ -54,6 +56,9 @@ public static RepositorySystem newRepositorySystem(final String factory) { switch (factory) { case SERVICE_LOCATOR: return org.apache.maven.resolver.examples.manual.ManualRepositorySystemFactory.newRepositorySystem(); + case SUPPLIER: + return org.apache.maven.resolver.examples.supplier.SupplierRepositorySystemFactory + .newRepositorySystem(); case GUICE: return org.apache.maven.resolver.examples.guice.GuiceRepositorySystemFactory.newRepositorySystem(); case SISU: diff --git a/maven-resolver-demos/maven-resolver-demo-snippets/src/test/java/org/apache/maven/resolver/examples/AllResolverDemosTest.java b/maven-resolver-demos/maven-resolver-demo-snippets/src/test/java/org/apache/maven/resolver/examples/AllResolverDemosTest.java index 40024aec4..ef31f936b 100644 --- a/maven-resolver-demos/maven-resolver-demo-snippets/src/test/java/org/apache/maven/resolver/examples/AllResolverDemosTest.java +++ b/maven-resolver-demos/maven-resolver-demo-snippets/src/test/java/org/apache/maven/resolver/examples/AllResolverDemosTest.java @@ -30,6 +30,11 @@ public void serviceLocator() throws Exception { AllResolverDemos.main(new String[] {Booter.SERVICE_LOCATOR}); } + @Test + public void supplier() throws Exception { + AllResolverDemos.main(new String[] {Booter.SUPPLIER}); + } + @Test public void guice() throws Exception { AllResolverDemos.main(new String[] {Booter.GUICE}); diff --git a/maven-resolver-demos/pom.xml b/maven-resolver-demos/pom.xml index ebbcc92b5..9342a7961 100644 --- a/maven-resolver-demos/pom.xml +++ b/maven-resolver-demos/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-demos @@ -37,11 +37,6 @@ maven-resolver-demo-maven-plugin - - - 3.8.7 - - diff --git a/maven-resolver-impl/pom.xml b/maven-resolver-impl/pom.xml index a206060cb..64614cb9d 100644 --- a/maven-resolver-impl/pom.xml +++ b/maven-resolver-impl/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-impl diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/DefaultServiceLocator.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/DefaultServiceLocator.java index 0c8f7598f..4f96f227f 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/DefaultServiceLocator.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/DefaultServiceLocator.java @@ -87,7 +87,8 @@ * Note: This class is not thread-safe. Clients are expected to create the service locator and the repository * system on a single thread. * - * @deprecated Use some out-of-the-box DI implementation instead. + * @deprecated Use of out-of-the-box DI implementation recommended, or, as alternative new supplier from + * module {@code maven-resolver-supplier}. */ @Deprecated public final class DefaultServiceLocator implements ServiceLocator { diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/UpdateCheck.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/UpdateCheck.java index f689c12fe..f5a2454e9 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/UpdateCheck.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/UpdateCheck.java @@ -43,6 +43,8 @@ public final class UpdateCheck { private String policy; + private String metadataPolicy; + private RemoteRepository repository; private RemoteRepository authoritativeRepository; @@ -147,19 +149,30 @@ public UpdateCheck setFileValid(boolean fileValid) { } /** - * Gets the policy to use for the check. + * Gets the policy to use for the data check. * - * @return The policy to use for the check. + * @return The policy to use for the data check. * @see org.eclipse.aether.repository.RepositoryPolicy */ public String getPolicy() { return policy; } + /** + * Gets the policy to use for the metadata check. + * + * @return The policy to use for the metadata check. + * @see org.eclipse.aether.repository.RepositoryPolicy + * @since TBD + */ + public String getMetadataPolicy() { + return metadataPolicy; + } + /** * Sets the policy to use for the check. * - * @param policy The policy to use for the check, may be {@code null}. + * @param policy The policy to use for the data check, may be {@code null}. * @return This object for chaining. * @see org.eclipse.aether.repository.RepositoryPolicy */ @@ -168,6 +181,19 @@ public UpdateCheck setPolicy(String policy) { return this; } + /** + * Sets the policy to use for the check. + * + * @param metadataPolicy The policy to use for the metadata check, may be {@code null}. + * @return This object for chaining. + * @see org.eclipse.aether.repository.RepositoryPolicy + * @since TBD + */ + public UpdateCheck setMetadataPolicy(String metadataPolicy) { + this.metadataPolicy = metadataPolicy; + return this; + } + /** * Gets the repository from which a potential update/download will performed. * @@ -256,6 +282,6 @@ public UpdateCheck setException(E exception) { @Override public String toString() { - return getPolicy() + ": " + getFile() + " < " + getRepository(); + return getPolicy() + "/" + getMetadataPolicy() + ": " + getFile() + " < " + getRepository(); } } diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/AetherModule.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/AetherModule.java index 1fef875bd..aad52e535 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/AetherModule.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/AetherModule.java @@ -128,7 +128,10 @@ * * @noextend This class must not be extended by clients and will eventually be marked {@code final} without prior * notice. + * @deprecated This class is about to be dropped in 2.0.0 release. Use SISU or use maven-resolver-supplier to + * get Resolver instances. */ +@Deprecated public class AetherModule extends AbstractModule { /** diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/package-info.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/package-info.java index a9ab92a79..91b686718 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/package-info.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/guice/package-info.java @@ -20,5 +20,7 @@ /** * The integration with the dependency injection framework * Google Guice. + * + * @deprecated This package is about to be dropped in 2.0.0. */ package org.eclipse.aether.impl.guice; diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/package-info.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/package-info.java index 7c7344f06..7c61005e1 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/package-info.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/package-info.java @@ -18,7 +18,7 @@ * under the License. */ /** - * The provisional interfaces defining the various sub components that implement the repository system. Aether Core + * The provisional interfaces defining the various subcomponents that implement the repository system. Aether Core * provides stock implementations for most of these components but not all. To obtain a complete/runnable repository * system, the application needs to provide implementations of the following component contracts: * {@link org.eclipse.aether.impl.ArtifactDescriptorReader}, {@link org.eclipse.aether.impl.VersionResolver}, 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 a77ab9064..164d42557 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 @@ -125,13 +125,14 @@ public class DefaultArtifactResolver implements ArtifactResolver, Service { private RemoteRepositoryFilterManager remoteRepositoryFilterManager; + @Deprecated public DefaultArtifactResolver() { // enables default constructor } @SuppressWarnings("checkstyle:parameternumber") @Inject - DefaultArtifactResolver( + public DefaultArtifactResolver( FileProcessor fileProcessor, RepositoryEventDispatcher repositoryEventDispatcher, VersionResolver versionResolver, @@ -581,6 +582,7 @@ private List gatherDownloads(RepositorySystemSession session, check.setFileValid(false); check.setRepository(group.repository); check.setPolicy(policy.getUpdatePolicy()); + check.setMetadataPolicy(policy.getMetadataUpdatePolicy()); item.updateCheck = check; updateCheckManager.checkArtifact(session, check); if (!check.isRequired()) { diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDeployer.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDeployer.java index be9df02c4..e451fa1a4 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDeployer.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDeployer.java @@ -97,13 +97,14 @@ public class DefaultDeployer implements Deployer, Service { private OfflineController offlineController; + @Deprecated public DefaultDeployer() { // enables default constructor } @SuppressWarnings("checkstyle:parameternumber") @Inject - DefaultDeployer( + public DefaultDeployer( FileProcessor fileProcessor, RepositoryEventDispatcher repositoryEventDispatcher, RepositoryConnectorProvider repositoryConnectorProvider, diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultInstaller.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultInstaller.java index 6ce59e6bb..c30f75a2e 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultInstaller.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultInstaller.java @@ -75,12 +75,13 @@ public class DefaultInstaller implements Installer, Service { private SyncContextFactory syncContextFactory; + @Deprecated public DefaultInstaller() { // enables default constructor } @Inject - DefaultInstaller( + public DefaultInstaller( FileProcessor fileProcessor, RepositoryEventDispatcher repositoryEventDispatcher, Set metadataFactories, diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultLocalRepositoryProvider.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultLocalRepositoryProvider.java index 201b79348..6be859f68 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultLocalRepositoryProvider.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultLocalRepositoryProvider.java @@ -50,12 +50,13 @@ public class DefaultLocalRepositoryProvider implements LocalRepositoryProvider, private Collection managerFactories = new ArrayList<>(); + @Deprecated public DefaultLocalRepositoryProvider() { // enables default constructor } @Inject - DefaultLocalRepositoryProvider(Set factories) { + public DefaultLocalRepositoryProvider(Set factories) { setLocalRepositoryManagerFactories(factories); } diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultMetadataResolver.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultMetadataResolver.java index a077d7ac3..b26de1d8d 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultMetadataResolver.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultMetadataResolver.java @@ -92,12 +92,13 @@ public class DefaultMetadataResolver implements MetadataResolver, Service { private RemoteRepositoryFilterManager remoteRepositoryFilterManager; + @Deprecated public DefaultMetadataResolver() { // enables default constructor } @Inject - DefaultMetadataResolver( + public DefaultMetadataResolver( RepositoryEventDispatcher repositoryEventDispatcher, UpdateCheckManager updateCheckManager, RepositoryConnectorProvider repositoryConnectorProvider, @@ -281,6 +282,8 @@ private List resolve( List> checks = new ArrayList<>(); Exception exception = null; for (RemoteRepository repo : repositories) { + RepositoryPolicy policy = getPolicy(session, repo, metadata.getNature()); + UpdateCheck check = new UpdateCheck<>(); check.setLocalLastUpdated((localLastUpdate != null) ? localLastUpdate : 0); check.setItem(metadata); @@ -293,8 +296,8 @@ private List resolve( check.setFile(checkFile); check.setRepository(repository); check.setAuthoritativeRepository(repo); - check.setPolicy( - getPolicy(session, repo, metadata.getNature()).getUpdatePolicy()); + check.setPolicy(policy.getUpdatePolicy()); + check.setMetadataPolicy(policy.getMetadataUpdatePolicy()); if (lrmResult.isStale()) { checks.add(check); @@ -434,11 +437,8 @@ private boolean isEnabled(RemoteRepository repository, Metadata.Nature nature) { && repository.getPolicy(false).isEnabled()) { return true; } - if (!Metadata.Nature.RELEASE.equals(nature) - && repository.getPolicy(true).isEnabled()) { - return true; - } - return false; + return !Metadata.Nature.RELEASE.equals(nature) + && repository.getPolicy(true).isEnabled(); } private RepositoryPolicy getPolicy( diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRemoteRepositoryManager.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRemoteRepositoryManager.java index 9a297555c..7844bc57d 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRemoteRepositoryManager.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRemoteRepositoryManager.java @@ -83,12 +83,13 @@ public int hashCode() { private ChecksumPolicyProvider checksumPolicyProvider; + @Deprecated public DefaultRemoteRepositoryManager() { // enables default constructor } @Inject - DefaultRemoteRepositoryManager( + public DefaultRemoteRepositoryManager( UpdatePolicyAnalyzer updatePolicyAnalyzer, ChecksumPolicyProvider checksumPolicyProvider) { setUpdatePolicyAnalyzer(updatePolicyAnalyzer); setChecksumPolicyProvider(checksumPolicyProvider); @@ -255,25 +256,41 @@ private RepositoryPolicy merge( if (policy2 == null) { if (globalPolicy) { - policy = merge(policy1, session.getUpdatePolicy(), session.getChecksumPolicy()); + policy = merge( + policy1, + session.getUpdatePolicy(), + session.getMetadataUpdatePolicy(), + session.getChecksumPolicy()); } else { policy = policy1; } } else if (policy1 == null) { if (globalPolicy) { - policy = merge(policy2, session.getUpdatePolicy(), session.getChecksumPolicy()); + policy = merge( + policy2, + session.getUpdatePolicy(), + session.getMetadataUpdatePolicy(), + session.getChecksumPolicy()); } else { policy = policy2; } } else if (!policy2.isEnabled()) { if (globalPolicy) { - policy = merge(policy1, session.getUpdatePolicy(), session.getChecksumPolicy()); + policy = merge( + policy1, + session.getUpdatePolicy(), + session.getMetadataUpdatePolicy(), + session.getChecksumPolicy()); } else { policy = policy1; } } else if (!policy1.isEnabled()) { if (globalPolicy) { - policy = merge(policy2, session.getUpdatePolicy(), session.getChecksumPolicy()); + policy = merge( + policy2, + session.getUpdatePolicy(), + session.getMetadataUpdatePolicy(), + session.getChecksumPolicy()); } else { policy = policy2; } @@ -295,24 +312,35 @@ private RepositoryPolicy merge( updates = updatePolicyAnalyzer.getEffectiveUpdatePolicy( session, policy1.getUpdatePolicy(), policy2.getUpdatePolicy()); } + String metadataUpdates = session.getMetadataUpdatePolicy(); + if (globalPolicy && metadataUpdates != null && !metadataUpdates.isEmpty()) { + // use global override + } else { + metadataUpdates = updatePolicyAnalyzer.getEffectiveUpdatePolicy( + session, policy1.getMetadataUpdatePolicy(), policy2.getMetadataUpdatePolicy()); + } - policy = new RepositoryPolicy(true, updates, checksums); + policy = new RepositoryPolicy(true, updates, metadataUpdates, checksums); } return policy; } - private RepositoryPolicy merge(RepositoryPolicy policy, String updates, String checksums) { + private RepositoryPolicy merge(RepositoryPolicy policy, String updates, String metadataUpdates, String checksums) { if (policy != null) { if (updates == null || updates.isEmpty()) { updates = policy.getUpdatePolicy(); } + if (metadataUpdates == null || metadataUpdates.isEmpty()) { + metadataUpdates = policy.getMetadataUpdatePolicy(); + } if (checksums == null || checksums.isEmpty()) { checksums = policy.getChecksumPolicy(); } if (!policy.getUpdatePolicy().equals(updates) + || !policy.getMetadataUpdatePolicy().equals(metadataUpdates) || !policy.getChecksumPolicy().equals(checksums)) { - policy = new RepositoryPolicy(policy.isEnabled(), updates, checksums); + policy = new RepositoryPolicy(policy.isEnabled(), updates, metadataUpdates, checksums); } } return policy; diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryConnectorProvider.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryConnectorProvider.java index 1f94cb2ef..b058eb0e0 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryConnectorProvider.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryConnectorProvider.java @@ -57,12 +57,13 @@ public class DefaultRepositoryConnectorProvider implements RepositoryConnectorPr private RemoteRepositoryFilterManager remoteRepositoryFilterManager; + @Deprecated public DefaultRepositoryConnectorProvider() { // enables default constructor } @Inject - DefaultRepositoryConnectorProvider( + public DefaultRepositoryConnectorProvider( Set connectorFactories, RemoteRepositoryFilterManager remoteRepositoryFilterManager) { setRepositoryConnectorFactories(connectorFactories); diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryEventDispatcher.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryEventDispatcher.java index 31b15292d..f603f1c0a 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryEventDispatcher.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryEventDispatcher.java @@ -46,12 +46,13 @@ public class DefaultRepositoryEventDispatcher implements RepositoryEventDispatch private Collection listeners = new ArrayList<>(); + @Deprecated public DefaultRepositoryEventDispatcher() { // enables no-arg constructor } @Inject - DefaultRepositoryEventDispatcher(Set listeners) { + public DefaultRepositoryEventDispatcher(Set listeners) { setRepositoryListeners(listeners); } diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryLayoutProvider.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryLayoutProvider.java index f555c684f..52cc6beaf 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryLayoutProvider.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryLayoutProvider.java @@ -50,12 +50,13 @@ public final class DefaultRepositoryLayoutProvider implements RepositoryLayoutPr private Collection factories = new ArrayList<>(); + @Deprecated public DefaultRepositoryLayoutProvider() { // enables default constructor } @Inject - DefaultRepositoryLayoutProvider(Set layoutFactories) { + public DefaultRepositoryLayoutProvider(Set layoutFactories) { setRepositoryLayoutFactories(layoutFactories); } diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositorySystem.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositorySystem.java index ef1b3e3f6..bc50c5201 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositorySystem.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositorySystem.java @@ -125,6 +125,7 @@ public class DefaultRepositorySystem implements RepositorySystem, Service { private RepositorySystemLifecycle repositorySystemLifecycle; + @Deprecated public DefaultRepositorySystem() { // enables default constructor this.shutdown = new AtomicBoolean(false); @@ -132,7 +133,7 @@ public DefaultRepositorySystem() { @SuppressWarnings("checkstyle:parameternumber") @Inject - DefaultRepositorySystem( + public DefaultRepositorySystem( VersionResolver versionResolver, VersionRangeResolver versionRangeResolver, ArtifactResolver artifactResolver, @@ -464,8 +465,7 @@ public List newResolutionRepositories( validateSession(session); validateRepositories(repositories); - repositories = remoteRepositoryManager.aggregateRepositories( - session, new ArrayList(), repositories, true); + repositories = remoteRepositoryManager.aggregateRepositories(session, new ArrayList<>(), repositories, true); return repositories; } diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultTransporterProvider.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultTransporterProvider.java index f7d10b19d..dd6823e96 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultTransporterProvider.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultTransporterProvider.java @@ -50,12 +50,13 @@ public final class DefaultTransporterProvider implements TransporterProvider, Se private Collection factories = new ArrayList<>(); + @Deprecated public DefaultTransporterProvider() { // enables default constructor } @Inject - DefaultTransporterProvider(Set transporterFactories) { + public DefaultTransporterProvider(Set transporterFactories) { setTransporterFactories(transporterFactories); } diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManager.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManager.java index 367bc2b2c..27ec290fb 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManager.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManager.java @@ -106,12 +106,14 @@ public String toString() { */ private static final long TS_UNKNOWN = 1L; + @Deprecated public DefaultUpdateCheckManager() { // default ctor for ServiceLocator } @Inject - DefaultUpdateCheckManager(TrackingFileManager trackingFileManager, UpdatePolicyAnalyzer updatePolicyAnalyzer) { + public DefaultUpdateCheckManager( + TrackingFileManager trackingFileManager, UpdatePolicyAnalyzer updatePolicyAnalyzer) { setTrackingFileManager(trackingFileManager); setUpdatePolicyAnalyzer(updatePolicyAnalyzer); } @@ -134,8 +136,9 @@ public DefaultUpdateCheckManager setUpdatePolicyAnalyzer(UpdatePolicyAnalyzer up public void checkArtifact(RepositorySystemSession session, UpdateCheck check) { requireNonNull(session, "session cannot be null"); requireNonNull(check, "check cannot be null"); + final String updatePolicy = check.getPolicy(); if (check.getLocalLastUpdated() != 0 - && !isUpdatedRequired(session, check.getLocalLastUpdated(), check.getPolicy())) { + && !isUpdatedRequired(session, check.getLocalLastUpdated(), updatePolicy)) { LOGGER.debug("Skipped remote request for {}, locally installed artifact up-to-date", check.getItem()); check.setRequired(false); @@ -185,7 +188,7 @@ public void checkArtifact(RepositorySystemSession session, UpdateCheck check) { requireNonNull(session, "session cannot be null"); requireNonNull(check, "check cannot be null"); + final String updatePolicy = check.getMetadataPolicy(); if (check.getLocalLastUpdated() != 0 - && !isUpdatedRequired(session, check.getLocalLastUpdated(), check.getPolicy())) { + && !isUpdatedRequired(session, check.getLocalLastUpdated(), updatePolicy)) { LOGGER.debug("Skipped remote request for {} locally installed metadata up-to-date", check.getItem()); check.setRequired(false); @@ -290,7 +294,7 @@ public void checkMetadata(RepositorySystemSession session, UpdateCheck delegates; diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/bf/BfDependencyCollector.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/bf/BfDependencyCollector.java index 56e6704e8..68a417579 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/bf/BfDependencyCollector.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/bf/BfDependencyCollector.java @@ -121,7 +121,7 @@ public BfDependencyCollector() { } @Inject - BfDependencyCollector( + public BfDependencyCollector( RemoteRepositoryManager remoteRepositoryManager, ArtifactDescriptorReader artifactDescriptorReader, VersionRangeResolver versionRangeResolver) { diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/df/DfDependencyCollector.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/df/DfDependencyCollector.java index f6d9900f4..5948d4fd8 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/df/DfDependencyCollector.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/df/DfDependencyCollector.java @@ -79,7 +79,7 @@ public DfDependencyCollector() { } @Inject - DfDependencyCollector( + public DfDependencyCollector( RemoteRepositoryManager remoteRepositoryManager, ArtifactDescriptorReader artifactDescriptorReader, VersionRangeResolver versionRangeResolver) { diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/legacy/DefaultSyncContextFactory.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/legacy/DefaultSyncContextFactory.java index 86e2d9666..71b7f09aa 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/legacy/DefaultSyncContextFactory.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/legacy/DefaultSyncContextFactory.java @@ -43,6 +43,7 @@ public final class DefaultSyncContextFactory implements org.eclipse.aether.impl.SyncContextFactory, Service { private SyncContextFactory delegate; + @Deprecated public DefaultSyncContextFactory() { // default ctor for ServiceLocator } diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManagerTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManagerTest.java index ab61d5754..dc9e32017 100644 --- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManagerTest.java +++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManagerTest.java @@ -106,6 +106,7 @@ private UpdateCheck newMetadataCheck() { check.setRepository(repository); check.setAuthoritativeRepository(repository); check.setPolicy(RepositoryPolicy.UPDATE_POLICY_INTERVAL + ":10"); + check.setMetadataPolicy(RepositoryPolicy.UPDATE_POLICY_INTERVAL + ":10"); return check; } @@ -298,6 +299,7 @@ public void testCheckMetadataErrorFromRepoCachingDisabled() { public void testCheckMetadataAtMostOnceDuringSessionEvenIfUpdatePolicyAlways() { UpdateCheck check = newMetadataCheck(); check.setPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); + check.setMetadataPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); // first check manager.checkMetadata(session, check); @@ -314,6 +316,7 @@ public void testCheckMetadataAtMostOnceDuringSessionEvenIfUpdatePolicyAlways() { public void testCheckMetadataSessionStateModes() { UpdateCheck check = newMetadataCheck(); check.setPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); + check.setMetadataPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); manager.touchMetadata(session, check); session.setConfigProperty(DefaultUpdateCheckManager.CONFIG_PROP_SESSION_STATE, "bypass"); @@ -338,6 +341,7 @@ public void testCheckMetadataSessionStateModes() { public void testCheckMetadataAtMostOnceDuringSessionEvenIfUpdatePolicyAlways_InvalidFile() { UpdateCheck check = newMetadataCheck(); check.setPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); + check.setMetadataPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); check.setFileValid(false); // first check @@ -364,6 +368,7 @@ public void testCheckMetadataAtMostOnceDuringSessionEvenIfUpdatePolicyAlways_Inv public void testCheckMetadataAtMostOnceDuringSessionEvenIfUpdatePolicyAlways_DifferentRepoIdSameUrl() { UpdateCheck check = newMetadataCheck(); check.setPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); + check.setMetadataPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); check.setFileValid(false); // first check @@ -427,6 +432,7 @@ public void testCheckMetadataWhenLocallyDeletedEvenIfTimestampUpToDate() { public void testCheckMetadataNotWhenUpdatePolicyIsNeverAndTimestampIsUnavailable() { UpdateCheck check = newMetadataCheck(); check.setPolicy(RepositoryPolicy.UPDATE_POLICY_NEVER); + check.setMetadataPolicy(RepositoryPolicy.UPDATE_POLICY_NEVER); session.setResolutionErrorPolicy(new SimpleResolutionErrorPolicy(true, false)); manager.checkMetadata(session, check); diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/StubFileTransformerManager.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/StubFileTransformerManager.java index 284858bbb..808f60537 100644 --- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/StubFileTransformerManager.java +++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/StubFileTransformerManager.java @@ -37,7 +37,7 @@ public Collection getTransformersForArtifact(Artifact artifact) public void addFileTransformer(String extension, FileTransformer fileTransformer) { if (!fileTransformers.containsKey(extension)) { - fileTransformers.put(extension, new HashSet()); + fileTransformers.put(extension, new HashSet<>()); } fileTransformers.get(extension).add(fileTransformer); } diff --git a/maven-resolver-named-locks-hazelcast/pom.xml b/maven-resolver-named-locks-hazelcast/pom.xml index 563b49d65..074417c87 100644 --- a/maven-resolver-named-locks-hazelcast/pom.xml +++ b/maven-resolver-named-locks-hazelcast/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-named-locks-hazelcast @@ -50,7 +50,7 @@ com.hazelcast hazelcast - 5.3.0 + 5.3.2 javax.inject diff --git a/maven-resolver-named-locks-redisson/pom.xml b/maven-resolver-named-locks-redisson/pom.xml index cf5cad489..ef8aab3f0 100644 --- a/maven-resolver-named-locks-redisson/pom.xml +++ b/maven-resolver-named-locks-redisson/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-named-locks-redisson @@ -50,7 +50,7 @@ org.redisson redisson - 3.21.3 + 3.23.4 org.slf4j @@ -135,7 +135,6 @@ org.apache.maven.plugins maven-assembly-plugin - 3.5.0 bundle diff --git a/maven-resolver-named-locks/pom.xml b/maven-resolver-named-locks/pom.xml index 27a320478..bb8f3dab2 100644 --- a/maven-resolver-named-locks/pom.xml +++ b/maven-resolver-named-locks/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-named-locks diff --git a/maven-resolver-spi/pom.xml b/maven-resolver-spi/pom.xml index 53bf13e11..78bfe7ac9 100644 --- a/maven-resolver-spi/pom.xml +++ b/maven-resolver-spi/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-spi diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locator/Service.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locator/Service.java index dcdf2c503..077c7662d 100644 --- a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locator/Service.java +++ b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locator/Service.java @@ -23,7 +23,8 @@ * means to programmatically wire the several components of the repository system together when it is used outside of an * IoC container. * - * @deprecated Use some out-of-the-box DI implementation instead. + * @deprecated Use of out-of-the-box DI implementation recommended, or, as alternative new supplier from + * module {@code maven-resolver-supplier}. */ @Deprecated public interface Service { diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locator/ServiceLocator.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locator/ServiceLocator.java index 5de51268a..ac2f34a60 100644 --- a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locator/ServiceLocator.java +++ b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locator/ServiceLocator.java @@ -32,7 +32,8 @@ * to acquire the repository system. Components that implement {@link Service} will be given an opportunity to acquire * further components from the locator, thereby allowing to create the complete object graph of the repository system. * - * @deprecated Use some out-of-the-box DI implementation instead. + * @deprecated Use of out-of-the-box DI implementation recommended, or, as alternative new supplier from + * module {@code maven-resolver-supplier}. */ @Deprecated public interface ServiceLocator { diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locator/package-info.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locator/package-info.java index e3d149387..75c08b6c8 100644 --- a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locator/package-info.java +++ b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/locator/package-info.java @@ -19,7 +19,7 @@ */ /** * A lightweight service locator infrastructure to help components acquire dependent components. The implementation of - * the repository system is decomposed into many sub components that interact with each other via interfaces, allowing + * the repository system is decomposed into many subcomponents that interact with each other via interfaces, allowing * an application to customize the system by swapping in different implementation classes for these interfaces. The * service locator defined by this package is one means for components to get hold of the proper implementation for its * dependencies. While not the most popular approach to component wiring, this service locator enables applications @@ -27,6 +27,7 @@ * footprint. Therefore, all components should implement {@link org.eclipse.aether.spi.locator.Service} to support this * goal. * - * @deprecated Use some out-of-the-box DI implementation instead. + * @deprecated Use of out-of-the-box DI implementation recommended, or, as alternative new supplier from + * module {@code maven-resolver-supplier}. */ package org.eclipse.aether.spi.locator; diff --git a/maven-resolver-supplier/pom.xml b/maven-resolver-supplier/pom.xml new file mode 100644 index 000000000..fee4e6e2a --- /dev/null +++ b/maven-resolver-supplier/pom.xml @@ -0,0 +1,148 @@ + + + + 4.0.0 + + + org.apache.maven.resolver + maven-resolver + 2.0.0-SNAPSHOT + + + maven-resolver-supplier + + Maven Artifact Resolver Instance Supplier + A helper module to provide RepositorySystem instances. + + + org.apache.maven.resolver.supplier + ${Automatic-Module-Name} + + + + + org.apache.maven.resolver + maven-resolver-api + + + org.apache.maven.resolver + maven-resolver-util + + + org.apache.maven.resolver + maven-resolver-spi + + + org.apache.maven.resolver + maven-resolver-named-locks + + + org.apache.maven.resolver + maven-resolver-impl + + + org.apache.maven.resolver + maven-resolver-connector-basic + + + org.apache.maven.resolver + maven-resolver-transport-file + + + org.apache.maven.resolver + maven-resolver-transport-http + + + + org.apache.maven + maven-resolver-provider + ${mavenVersion} + + + javax.inject + javax.inject + + + org.eclipse.sisu + org.eclipse.sisu.inject + + + + + org.apache.maven + maven-model-builder + ${mavenVersion} + + + javax.inject + javax.inject + + + org.eclipse.sisu + org.eclipse.sisu.inject + + + + + + org.slf4j + slf4j-api + + + + org.slf4j + slf4j-simple + test + + + org.hamcrest + hamcrest + test + + + org.hamcrest + hamcrest-core + test + + + junit + junit + test + + + + + + + biz.aQute.bnd + bnd-maven-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + + diff --git a/maven-resolver-supplier/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java b/maven-resolver-supplier/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java new file mode 100644 index 000000000..795265679 --- /dev/null +++ b/maven-resolver-supplier/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java @@ -0,0 +1,638 @@ +/* + * 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.HashMap; +import java.util.HashSet; +import java.util.Map; +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.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; +import org.eclipse.aether.impl.ArtifactDescriptorReader; +import org.eclipse.aether.impl.ArtifactResolver; +import org.eclipse.aether.impl.DependencyCollector; +import org.eclipse.aether.impl.Deployer; +import org.eclipse.aether.impl.Installer; +import org.eclipse.aether.impl.LocalRepositoryProvider; +import org.eclipse.aether.impl.MetadataGeneratorFactory; +import org.eclipse.aether.impl.MetadataResolver; +import org.eclipse.aether.impl.OfflineController; +import org.eclipse.aether.impl.RemoteRepositoryFilterManager; +import org.eclipse.aether.impl.RemoteRepositoryManager; +import org.eclipse.aether.impl.RepositoryConnectorProvider; +import org.eclipse.aether.impl.RepositoryEventDispatcher; +import org.eclipse.aether.impl.RepositorySystemLifecycle; +import org.eclipse.aether.impl.UpdateCheckManager; +import org.eclipse.aether.impl.UpdatePolicyAnalyzer; +import org.eclipse.aether.impl.VersionRangeResolver; +import org.eclipse.aether.impl.VersionResolver; +import org.eclipse.aether.internal.impl.DefaultArtifactResolver; +import org.eclipse.aether.internal.impl.DefaultChecksumPolicyProvider; +import org.eclipse.aether.internal.impl.DefaultDeployer; +import org.eclipse.aether.internal.impl.DefaultFileProcessor; +import org.eclipse.aether.internal.impl.DefaultInstaller; +import org.eclipse.aether.internal.impl.DefaultLocalPathComposer; +import org.eclipse.aether.internal.impl.DefaultLocalPathPrefixComposerFactory; +import org.eclipse.aether.internal.impl.DefaultLocalRepositoryProvider; +import org.eclipse.aether.internal.impl.DefaultMetadataResolver; +import org.eclipse.aether.internal.impl.DefaultOfflineController; +import org.eclipse.aether.internal.impl.DefaultRemoteRepositoryManager; +import org.eclipse.aether.internal.impl.DefaultRepositoryConnectorProvider; +import org.eclipse.aether.internal.impl.DefaultRepositoryEventDispatcher; +import org.eclipse.aether.internal.impl.DefaultRepositoryLayoutProvider; +import org.eclipse.aether.internal.impl.DefaultRepositorySystem; +import org.eclipse.aether.internal.impl.DefaultRepositorySystemLifecycle; +import org.eclipse.aether.internal.impl.DefaultTrackingFileManager; +import org.eclipse.aether.internal.impl.DefaultTransporterProvider; +import org.eclipse.aether.internal.impl.DefaultUpdateCheckManager; +import org.eclipse.aether.internal.impl.DefaultUpdatePolicyAnalyzer; +import org.eclipse.aether.internal.impl.EnhancedLocalRepositoryManagerFactory; +import org.eclipse.aether.internal.impl.LocalPathComposer; +import org.eclipse.aether.internal.impl.LocalPathPrefixComposerFactory; +import org.eclipse.aether.internal.impl.Maven2RepositoryLayoutFactory; +import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory; +import org.eclipse.aether.internal.impl.TrackingFileManager; +import org.eclipse.aether.internal.impl.checksum.DefaultChecksumAlgorithmFactorySelector; +import org.eclipse.aether.internal.impl.checksum.Md5ChecksumAlgorithmFactory; +import org.eclipse.aether.internal.impl.checksum.Sha1ChecksumAlgorithmFactory; +import org.eclipse.aether.internal.impl.checksum.Sha256ChecksumAlgorithmFactory; +import org.eclipse.aether.internal.impl.checksum.Sha512ChecksumAlgorithmFactory; +import org.eclipse.aether.internal.impl.checksum.SparseDirectoryTrustedChecksumsSource; +import org.eclipse.aether.internal.impl.checksum.SummaryFileTrustedChecksumsSource; +import org.eclipse.aether.internal.impl.checksum.TrustedToProvidedChecksumsSourceAdapter; +import org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector; +import org.eclipse.aether.internal.impl.collect.DependencyCollectorDelegate; +import org.eclipse.aether.internal.impl.collect.bf.BfDependencyCollector; +import org.eclipse.aether.internal.impl.collect.df.DfDependencyCollector; +import org.eclipse.aether.internal.impl.filter.DefaultRemoteRepositoryFilterManager; +import org.eclipse.aether.internal.impl.filter.GroupIdRemoteRepositoryFilterSource; +import org.eclipse.aether.internal.impl.filter.PrefixesRemoteRepositoryFilterSource; +import org.eclipse.aether.internal.impl.resolution.TrustedChecksumsArtifactResolverPostProcessor; +import org.eclipse.aether.internal.impl.synccontext.DefaultSyncContextFactory; +import org.eclipse.aether.internal.impl.synccontext.named.NameMapper; +import org.eclipse.aether.internal.impl.synccontext.named.NameMappers; +import org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactoryAdapterFactory; +import org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactoryAdapterFactoryImpl; +import org.eclipse.aether.named.NamedLockFactory; +import org.eclipse.aether.named.providers.FileLockNamedLockFactory; +import org.eclipse.aether.named.providers.LocalReadWriteLockNamedLockFactory; +import org.eclipse.aether.named.providers.LocalSemaphoreNamedLockFactory; +import org.eclipse.aether.named.providers.NoopNamedLockFactory; +import org.eclipse.aether.spi.checksums.ProvidedChecksumsSource; +import org.eclipse.aether.spi.checksums.TrustedChecksumsSource; +import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; +import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory; +import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector; +import org.eclipse.aether.spi.connector.checksum.ChecksumPolicyProvider; +import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilterSource; +import org.eclipse.aether.spi.connector.layout.RepositoryLayoutFactory; +import org.eclipse.aether.spi.connector.layout.RepositoryLayoutProvider; +import org.eclipse.aether.spi.connector.transport.TransporterFactory; +import org.eclipse.aether.spi.connector.transport.TransporterProvider; +import org.eclipse.aether.spi.io.FileProcessor; +import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory; +import org.eclipse.aether.spi.resolution.ArtifactResolverPostProcessor; +import org.eclipse.aether.spi.synccontext.SyncContextFactory; +import org.eclipse.aether.transport.file.FileTransporterFactory; +import org.eclipse.aether.transport.http.ChecksumExtractor; +import org.eclipse.aether.transport.http.HttpTransporterFactory; +import org.eclipse.aether.transport.http.Nexus2ChecksumExtractor; +import org.eclipse.aether.transport.http.XChecksumChecksumExtractor; + +/** + * A simple {@link Supplier} of {@link org.eclipse.aether.RepositorySystem} instances, that on each call supplies newly + * constructed instance. For proper shut down, use {@link RepositorySystem#shutdown()} method on supplied instance(s). + *

+ * Extend this class and override methods to customize, if needed. + * + * @since 1.9.15 + */ +public class RepositorySystemSupplier implements Supplier { + protected FileProcessor getFileProcessor() { + return new DefaultFileProcessor(); + } + + protected TrackingFileManager getTrackingFileManager() { + return new DefaultTrackingFileManager(); + } + + protected LocalPathComposer getLocalPathComposer() { + return new DefaultLocalPathComposer(); + } + + protected LocalPathPrefixComposerFactory getLocalPathPrefixComposerFactory() { + return new DefaultLocalPathPrefixComposerFactory(); + } + + protected RepositorySystemLifecycle getRepositorySystemLifecycle() { + return new DefaultRepositorySystemLifecycle(); + } + + protected OfflineController getOfflineController() { + return new DefaultOfflineController(); + } + + protected UpdatePolicyAnalyzer getUpdatePolicyAnalyzer() { + return new DefaultUpdatePolicyAnalyzer(); + } + + protected ChecksumPolicyProvider getChecksumPolicyProvider() { + return new DefaultChecksumPolicyProvider(); + } + + protected UpdateCheckManager getUpdateCheckManager( + TrackingFileManager trackingFileManager, UpdatePolicyAnalyzer updatePolicyAnalyzer) { + return new DefaultUpdateCheckManager(trackingFileManager, updatePolicyAnalyzer); + } + + protected Map getNamedLockFactories() { + HashMap result = new HashMap<>(); + result.put(NoopNamedLockFactory.NAME, new NoopNamedLockFactory()); + result.put(LocalReadWriteLockNamedLockFactory.NAME, new LocalReadWriteLockNamedLockFactory()); + result.put(LocalSemaphoreNamedLockFactory.NAME, new LocalSemaphoreNamedLockFactory()); + result.put(FileLockNamedLockFactory.NAME, new FileLockNamedLockFactory()); + return result; + } + + protected Map getNameMappers() { + HashMap result = new HashMap<>(); + result.put(NameMappers.STATIC_NAME, NameMappers.staticNameMapper()); + result.put(NameMappers.GAV_NAME, NameMappers.gavNameMapper()); + result.put(NameMappers.DISCRIMINATING_NAME, NameMappers.discriminatingNameMapper()); + result.put(NameMappers.FILE_GAV_NAME, NameMappers.fileGavNameMapper()); + result.put(NameMappers.FILE_HGAV_NAME, NameMappers.fileHashingGavNameMapper()); + return result; + } + + protected NamedLockFactoryAdapterFactory getNamedLockFactoryAdapterFactory( + Map namedLockFactories, + Map nameMappers, + RepositorySystemLifecycle repositorySystemLifecycle) { + return new NamedLockFactoryAdapterFactoryImpl(namedLockFactories, nameMappers, repositorySystemLifecycle); + } + + protected SyncContextFactory getSyncContextFactory(NamedLockFactoryAdapterFactory namedLockFactoryAdapterFactory) { + return new DefaultSyncContextFactory(namedLockFactoryAdapterFactory); + } + + protected Map getChecksumAlgorithmFactories() { + HashMap result = new HashMap<>(); + result.put(Sha512ChecksumAlgorithmFactory.NAME, new Sha512ChecksumAlgorithmFactory()); + result.put(Sha256ChecksumAlgorithmFactory.NAME, new Sha256ChecksumAlgorithmFactory()); + result.put(Sha1ChecksumAlgorithmFactory.NAME, new Sha1ChecksumAlgorithmFactory()); + result.put(Md5ChecksumAlgorithmFactory.NAME, new Md5ChecksumAlgorithmFactory()); + return result; + } + + protected ChecksumAlgorithmFactorySelector getChecksumAlgorithmFactorySelector( + Map checksumAlgorithmFactories) { + return new DefaultChecksumAlgorithmFactorySelector(checksumAlgorithmFactories); + } + + protected Map getRepositoryLayoutFactories( + ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector) { + HashMap result = new HashMap<>(); + result.put( + Maven2RepositoryLayoutFactory.NAME, + new Maven2RepositoryLayoutFactory(checksumAlgorithmFactorySelector)); + return result; + } + + protected RepositoryLayoutProvider getRepositoryLayoutProvider( + Map repositoryLayoutFactories) { + return new DefaultRepositoryLayoutProvider(new HashSet<>(repositoryLayoutFactories.values())); + } + + protected LocalRepositoryProvider getLocalRepositoryProvider( + LocalPathComposer localPathComposer, + TrackingFileManager trackingFileManager, + LocalPathPrefixComposerFactory localPathPrefixComposerFactory) { + HashSet localRepositoryProviders = new HashSet<>(2); + localRepositoryProviders.add(new SimpleLocalRepositoryManagerFactory(localPathComposer)); + localRepositoryProviders.add(new EnhancedLocalRepositoryManagerFactory( + localPathComposer, trackingFileManager, localPathPrefixComposerFactory)); + return new DefaultLocalRepositoryProvider(localRepositoryProviders); + } + + protected RemoteRepositoryManager getRemoteRepositoryManager( + UpdatePolicyAnalyzer updatePolicyAnalyzer, ChecksumPolicyProvider checksumPolicyProvider) { + return new DefaultRemoteRepositoryManager(updatePolicyAnalyzer, checksumPolicyProvider); + } + + protected Map getRemoteRepositoryFilterSources( + RepositorySystemLifecycle repositorySystemLifecycle, RepositoryLayoutProvider repositoryLayoutProvider) { + HashMap result = new HashMap<>(); + result.put( + GroupIdRemoteRepositoryFilterSource.NAME, + new GroupIdRemoteRepositoryFilterSource(repositorySystemLifecycle)); + result.put( + PrefixesRemoteRepositoryFilterSource.NAME, + new PrefixesRemoteRepositoryFilterSource(repositoryLayoutProvider)); + return result; + } + + protected RemoteRepositoryFilterManager getRemoteRepositoryFilterManager( + Map remoteRepositoryFilterSources) { + return new DefaultRemoteRepositoryFilterManager(remoteRepositoryFilterSources); + } + + protected Map getRepositoryListeners() { + return new HashMap<>(); + } + + protected RepositoryEventDispatcher getRepositoryEventDispatcher( + Map repositoryListeners) { + return new DefaultRepositoryEventDispatcher(new HashSet<>(repositoryListeners.values())); + } + + protected Map getTrustedChecksumsSources( + FileProcessor fileProcessor, + LocalPathComposer localPathComposer, + RepositorySystemLifecycle repositorySystemLifecycle) { + HashMap result = new HashMap<>(); + result.put( + SparseDirectoryTrustedChecksumsSource.NAME, + new SparseDirectoryTrustedChecksumsSource(fileProcessor, localPathComposer)); + result.put( + SummaryFileTrustedChecksumsSource.NAME, + new SummaryFileTrustedChecksumsSource(localPathComposer, repositorySystemLifecycle)); + return result; + } + + protected Map getProvidedChecksumsSources( + Map trustedChecksumsSources) { + HashMap result = new HashMap<>(); + result.put( + TrustedToProvidedChecksumsSourceAdapter.NAME, + new TrustedToProvidedChecksumsSourceAdapter(trustedChecksumsSources)); + return result; + } + + protected Map getChecksumExtractors() { + HashMap result = new HashMap<>(); + result.put(Nexus2ChecksumExtractor.NAME, new Nexus2ChecksumExtractor()); + result.put(XChecksumChecksumExtractor.NAME, new XChecksumChecksumExtractor()); + return result; + } + + protected Map getTransporterFactories(Map extractors) { + HashMap result = new HashMap<>(); + result.put(FileTransporterFactory.NAME, new FileTransporterFactory()); + result.put(HttpTransporterFactory.NAME, new HttpTransporterFactory(extractors)); + return result; + } + + protected TransporterProvider getTransporterProvider(Map transporterFactories) { + return new DefaultTransporterProvider(new HashSet<>(transporterFactories.values())); + } + + protected BasicRepositoryConnectorFactory getBasicRepositoryConnectorFactory( + TransporterProvider transporterProvider, + RepositoryLayoutProvider repositoryLayoutProvider, + ChecksumPolicyProvider checksumPolicyProvider, + FileProcessor fileProcessor, + Map providedChecksumsSources) { + return new BasicRepositoryConnectorFactory( + transporterProvider, + repositoryLayoutProvider, + checksumPolicyProvider, + fileProcessor, + providedChecksumsSources); + } + + protected Map getRepositoryConnectorFactories( + BasicRepositoryConnectorFactory basicRepositoryConnectorFactory) { + HashMap result = new HashMap<>(); + result.put(BasicRepositoryConnectorFactory.NAME, basicRepositoryConnectorFactory); + return result; + } + + protected RepositoryConnectorProvider getRepositoryConnectorProvider( + Map repositoryConnectorFactories, + RemoteRepositoryFilterManager remoteRepositoryFilterManager) { + return new DefaultRepositoryConnectorProvider( + new HashSet<>(repositoryConnectorFactories.values()), remoteRepositoryFilterManager); + } + + protected Installer getInstaller( + FileProcessor fileProcessor, + RepositoryEventDispatcher repositoryEventDispatcher, + Map metadataGeneratorFactories, + SyncContextFactory syncContextFactory) { + return new DefaultInstaller( + fileProcessor, + repositoryEventDispatcher, + new HashSet<>(metadataGeneratorFactories.values()), + syncContextFactory); + } + + @SuppressWarnings("checkstyle:parameternumber") + protected Deployer getDeployer( + FileProcessor fileProcessor, + RepositoryEventDispatcher repositoryEventDispatcher, + RepositoryConnectorProvider repositoryConnectorProvider, + RemoteRepositoryManager remoteRepositoryManager, + UpdateCheckManager updateCheckManager, + Map metadataGeneratorFactories, + SyncContextFactory syncContextFactory, + OfflineController offlineController) { + return new DefaultDeployer( + fileProcessor, + repositoryEventDispatcher, + repositoryConnectorProvider, + remoteRepositoryManager, + updateCheckManager, + new HashSet<>(metadataGeneratorFactories.values()), + syncContextFactory, + offlineController); + } + + protected Map getDependencyCollectorDelegates( + RemoteRepositoryManager remoteRepositoryManager, + ArtifactDescriptorReader artifactDescriptorReader, + VersionRangeResolver versionRangeResolver) { + HashMap result = new HashMap<>(); + result.put( + DfDependencyCollector.NAME, + new DfDependencyCollector(remoteRepositoryManager, artifactDescriptorReader, versionRangeResolver)); + result.put( + BfDependencyCollector.NAME, + new BfDependencyCollector(remoteRepositoryManager, artifactDescriptorReader, versionRangeResolver)); + return result; + } + + protected DependencyCollector getDependencyCollector( + Map dependencyCollectorDelegates) { + return new DefaultDependencyCollector(dependencyCollectorDelegates); + } + + protected Map getArtifactResolverPostProcessors( + ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector, + Map trustedChecksumsSources) { + HashMap result = new HashMap<>(); + result.put( + TrustedChecksumsArtifactResolverPostProcessor.NAME, + new TrustedChecksumsArtifactResolverPostProcessor( + checksumAlgorithmFactorySelector, trustedChecksumsSources)); + return result; + } + + @SuppressWarnings("checkstyle:parameternumber") + protected ArtifactResolver getArtifactResolver( + FileProcessor fileProcessor, + RepositoryEventDispatcher repositoryEventDispatcher, + VersionResolver versionResolver, + UpdateCheckManager updateCheckManager, + RepositoryConnectorProvider repositoryConnectorProvider, + RemoteRepositoryManager remoteRepositoryManager, + SyncContextFactory syncContextFactory, + OfflineController offlineController, + Map artifactResolverPostProcessors, + RemoteRepositoryFilterManager remoteRepositoryFilterManager) { + return new DefaultArtifactResolver( + fileProcessor, + repositoryEventDispatcher, + versionResolver, + updateCheckManager, + repositoryConnectorProvider, + remoteRepositoryManager, + syncContextFactory, + offlineController, + artifactResolverPostProcessors, + remoteRepositoryFilterManager); + } + + protected MetadataResolver getMetadataResolver( + RepositoryEventDispatcher repositoryEventDispatcher, + UpdateCheckManager updateCheckManager, + RepositoryConnectorProvider repositoryConnectorProvider, + RemoteRepositoryManager remoteRepositoryManager, + SyncContextFactory syncContextFactory, + OfflineController offlineController, + RemoteRepositoryFilterManager remoteRepositoryFilterManager) { + return new DefaultMetadataResolver( + repositoryEventDispatcher, + updateCheckManager, + repositoryConnectorProvider, + remoteRepositoryManager, + syncContextFactory, + offlineController, + remoteRepositoryFilterManager); + } + + // Maven provided + + protected Map getMetadataGeneratorFactories() { + // from maven-resolver-provider + HashMap result = new HashMap<>(); + result.put(PluginsMetadataGeneratorFactory.NAME, new PluginsMetadataGeneratorFactory()); + result.put(VersionsMetadataGeneratorFactory.NAME, new VersionsMetadataGeneratorFactory()); + result.put(SnapshotMetadataGeneratorFactory.NAME, new SnapshotMetadataGeneratorFactory()); + return result; + } + + protected ArtifactDescriptorReader getArtifactDescriptorReader( + RemoteRepositoryManager remoteRepositoryManager, + VersionResolver versionResolver, + VersionRangeResolver versionRangeResolver, + ArtifactResolver artifactResolver, + ModelBuilder modelBuilder, + RepositoryEventDispatcher repositoryEventDispatcher, + ModelCacheFactory modelCacheFactory) { + // from maven-resolver-provider + return new DefaultArtifactDescriptorReader( + remoteRepositoryManager, + versionResolver, + versionRangeResolver, + artifactResolver, + modelBuilder, + repositoryEventDispatcher, + modelCacheFactory); + } + + protected VersionResolver getVersionResolver( + MetadataResolver metadataResolver, + SyncContextFactory syncContextFactory, + RepositoryEventDispatcher repositoryEventDispatcher) { + // from maven-resolver-provider + return new DefaultVersionResolver(metadataResolver, syncContextFactory, repositoryEventDispatcher); + } + + protected VersionRangeResolver getVersionRangeResolver( + MetadataResolver metadataResolver, + SyncContextFactory syncContextFactory, + RepositoryEventDispatcher repositoryEventDispatcher) { + // from maven-resolver-provider + return new DefaultVersionRangeResolver(metadataResolver, syncContextFactory, repositoryEventDispatcher); + } + + protected ModelBuilder getModelBuilder() { + // from maven-model-builder + return new DefaultModelBuilderFactory().newInstance(); + } + + protected ModelCacheFactory getModelCacheFactory() { + // from maven-resolver-provider + return new DefaultModelCacheFactory(); + } + + @Override + public RepositorySystem get() { + FileProcessor fileProcessor = getFileProcessor(); + TrackingFileManager trackingFileManager = getTrackingFileManager(); + LocalPathComposer localPathComposer = getLocalPathComposer(); + LocalPathPrefixComposerFactory localPathPrefixComposerFactory = getLocalPathPrefixComposerFactory(); + RepositorySystemLifecycle repositorySystemLifecycle = getRepositorySystemLifecycle(); + OfflineController offlineController = getOfflineController(); + UpdatePolicyAnalyzer updatePolicyAnalyzer = getUpdatePolicyAnalyzer(); + ChecksumPolicyProvider checksumPolicyProvider = getChecksumPolicyProvider(); + + UpdateCheckManager updateCheckManager = getUpdateCheckManager(trackingFileManager, updatePolicyAnalyzer); + + Map namedLockFactories = getNamedLockFactories(); + Map nameMappers = getNameMappers(); + NamedLockFactoryAdapterFactory namedLockFactoryAdapterFactory = + getNamedLockFactoryAdapterFactory(namedLockFactories, nameMappers, repositorySystemLifecycle); + SyncContextFactory syncContextFactory = getSyncContextFactory(namedLockFactoryAdapterFactory); + + Map checksumAlgorithmFactories = getChecksumAlgorithmFactories(); + ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector = + getChecksumAlgorithmFactorySelector(checksumAlgorithmFactories); + + Map repositoryLayoutFactories = + getRepositoryLayoutFactories(checksumAlgorithmFactorySelector); + RepositoryLayoutProvider repositoryLayoutProvider = getRepositoryLayoutProvider(repositoryLayoutFactories); + + LocalRepositoryProvider localRepositoryProvider = + getLocalRepositoryProvider(localPathComposer, trackingFileManager, localPathPrefixComposerFactory); + + RemoteRepositoryManager remoteRepositoryManager = + getRemoteRepositoryManager(updatePolicyAnalyzer, checksumPolicyProvider); + Map remoteRepositoryFilterSources = + getRemoteRepositoryFilterSources(repositorySystemLifecycle, repositoryLayoutProvider); + RemoteRepositoryFilterManager remoteRepositoryFilterManager = + getRemoteRepositoryFilterManager(remoteRepositoryFilterSources); + + Map repositoryListeners = getRepositoryListeners(); + RepositoryEventDispatcher repositoryEventDispatcher = getRepositoryEventDispatcher(repositoryListeners); + + Map trustedChecksumsSources = + getTrustedChecksumsSources(fileProcessor, localPathComposer, repositorySystemLifecycle); + Map providedChecksumsSources = + getProvidedChecksumsSources(trustedChecksumsSources); + + Map checksumExtractors = getChecksumExtractors(); + Map transporterFactories = getTransporterFactories(checksumExtractors); + TransporterProvider transporterProvider = getTransporterProvider(transporterFactories); + + BasicRepositoryConnectorFactory basic = getBasicRepositoryConnectorFactory( + transporterProvider, + repositoryLayoutProvider, + checksumPolicyProvider, + fileProcessor, + providedChecksumsSources); + Map repositoryConnectorFactories = getRepositoryConnectorFactories(basic); + RepositoryConnectorProvider repositoryConnectorProvider = + getRepositoryConnectorProvider(repositoryConnectorFactories, remoteRepositoryFilterManager); + + Map metadataGeneratorFactories = getMetadataGeneratorFactories(); + + Installer installer = + getInstaller(fileProcessor, repositoryEventDispatcher, metadataGeneratorFactories, syncContextFactory); + Deployer deployer = getDeployer( + fileProcessor, + repositoryEventDispatcher, + repositoryConnectorProvider, + remoteRepositoryManager, + updateCheckManager, + metadataGeneratorFactories, + syncContextFactory, + offlineController); + + MetadataResolver metadataResolver = getMetadataResolver( + repositoryEventDispatcher, + updateCheckManager, + repositoryConnectorProvider, + remoteRepositoryManager, + syncContextFactory, + offlineController, + remoteRepositoryFilterManager); + + VersionResolver versionResolver = + getVersionResolver(metadataResolver, syncContextFactory, repositoryEventDispatcher); + VersionRangeResolver versionRangeResolver = + getVersionRangeResolver(metadataResolver, syncContextFactory, repositoryEventDispatcher); + + Map artifactResolverPostProcessors = + getArtifactResolverPostProcessors(checksumAlgorithmFactorySelector, trustedChecksumsSources); + ArtifactResolver artifactResolver = getArtifactResolver( + fileProcessor, + repositoryEventDispatcher, + versionResolver, + updateCheckManager, + repositoryConnectorProvider, + remoteRepositoryManager, + syncContextFactory, + offlineController, + artifactResolverPostProcessors, + remoteRepositoryFilterManager); + + ModelBuilder modelBuilder = getModelBuilder(); + ModelCacheFactory modelCacheFactory = getModelCacheFactory(); + + ArtifactDescriptorReader artifactDescriptorReader = getArtifactDescriptorReader( + remoteRepositoryManager, + versionResolver, + versionRangeResolver, + artifactResolver, + modelBuilder, + repositoryEventDispatcher, + modelCacheFactory); + + Map dependencyCollectorDelegates = getDependencyCollectorDelegates( + remoteRepositoryManager, artifactDescriptorReader, versionRangeResolver); + DependencyCollector dependencyCollector = getDependencyCollector(dependencyCollectorDelegates); + + return new DefaultRepositorySystem( + versionResolver, + versionRangeResolver, + artifactResolver, + metadataResolver, + artifactDescriptorReader, + dependencyCollector, + installer, + deployer, + localRepositoryProvider, + syncContextFactory, + remoteRepositoryManager, + repositorySystemLifecycle); + } +} diff --git a/maven-resolver-supplier/src/test/java/org/eclipse/aether/supplier/RepositorySystemSupplierTest.java b/maven-resolver-supplier/src/test/java/org/eclipse/aether/supplier/RepositorySystemSupplierTest.java new file mode 100644 index 000000000..ffedd07ca --- /dev/null +++ b/maven-resolver-supplier/src/test/java/org/eclipse/aether/supplier/RepositorySystemSupplierTest.java @@ -0,0 +1,68 @@ +/* + * 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.Collections; +import java.util.List; + +import org.apache.maven.repository.internal.MavenRepositorySystemUtils; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.repository.LocalRepository; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.VersionRangeRequest; +import org.eclipse.aether.resolution.VersionRangeResult; +import org.eclipse.aether.version.Version; +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.hasSize; + +public class RepositorySystemSupplierTest { + private final RepositorySystemSupplier subject = new RepositorySystemSupplier(); + + public static DefaultRepositorySystemSession newRepositorySystemSession(RepositorySystem system) { + DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); + LocalRepository localRepo = new LocalRepository("target/local-repo"); + session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo)); + return session; + } + + @Test + public void smoke() throws Exception { + RepositorySystem system = subject.get(); + RepositorySystemSession session = newRepositorySystemSession(system); + + Artifact artifact = new DefaultArtifact("org.apache.maven.resolver:maven-resolver-util:[0,)"); + VersionRangeRequest rangeRequest = new VersionRangeRequest(); + rangeRequest.setArtifact(artifact); + rangeRequest.setRepositories(Collections.singletonList( + new RemoteRepository.Builder("central", "default", "https://repo.maven.apache.org/maven2/").build())); + VersionRangeResult rangeResult = system.resolveVersionRange(session, rangeRequest); + List versions = rangeResult.getVersions(); + + // As of 2023-08-01, Maven Central has 33 versions of this artifact (and it will just grow) + assertThat(versions, hasSize(greaterThanOrEqualTo(33))); + System.out.println("Available versions " + versions); + } +} diff --git a/maven-resolver-test-util/pom.xml b/maven-resolver-test-util/pom.xml index 6f3709712..5431cb1d7 100644 --- a/maven-resolver-test-util/pom.xml +++ b/maven-resolver-test-util/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-test-util diff --git a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/IniArtifactDataReader.java b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/IniArtifactDataReader.java index 3d0718dd2..c524acfb4 100644 --- a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/IniArtifactDataReader.java +++ b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/IniArtifactDataReader.java @@ -118,7 +118,7 @@ private ArtifactDescription parse(Reader reader) throws IOException { String name = line.substring(1, line.length() - 1); name = name.replace("-", "").toUpperCase(Locale.ENGLISH); state = State.valueOf(name); - sections.put(state, new ArrayList()); + sections.put(state, new ArrayList<>()); } catch (IllegalArgumentException e) { throw new IOException("unknown section: " + line); } diff --git a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileUtils.java b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileUtils.java index acf175565..3eae72dba 100644 --- a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileUtils.java +++ b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestFileUtils.java @@ -240,6 +240,11 @@ public static void writeString(File file, String content) throws IOException { writeBytes(file, content.getBytes(StandardCharsets.UTF_8), 1); } + public static void writeString(File file, String content, long timestamp) throws IOException { + writeBytes(file, content.getBytes(StandardCharsets.UTF_8), 1); + file.setLastModified(timestamp); + } + public static void readProps(File file, Properties props) throws IOException { FileInputStream fis = null; try { diff --git a/maven-resolver-transport-classpath/pom.xml b/maven-resolver-transport-classpath/pom.xml index 03f1a5e68..f49877505 100644 --- a/maven-resolver-transport-classpath/pom.xml +++ b/maven-resolver-transport-classpath/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-transport-classpath diff --git a/maven-resolver-transport-classpath/src/main/java/org/eclipse/aether/transport/classpath/ClasspathTransporterFactory.java b/maven-resolver-transport-classpath/src/main/java/org/eclipse/aether/transport/classpath/ClasspathTransporterFactory.java index 772a28e53..c0a6c6133 100644 --- a/maven-resolver-transport-classpath/src/main/java/org/eclipse/aether/transport/classpath/ClasspathTransporterFactory.java +++ b/maven-resolver-transport-classpath/src/main/java/org/eclipse/aether/transport/classpath/ClasspathTransporterFactory.java @@ -36,8 +36,9 @@ *

* Note: Such repositories are read-only and uploads to them are generally not supported. */ -@Named("classpath") +@Named(ClasspathTransporterFactory.NAME) public final class ClasspathTransporterFactory implements TransporterFactory { + public static final String NAME = "classpath"; /** * The key in the repository session's {@link RepositorySystemSession#getConfigProperties() configuration diff --git a/maven-resolver-transport-file/pom.xml b/maven-resolver-transport-file/pom.xml index 7ede9ce6d..89ce65de2 100644 --- a/maven-resolver-transport-file/pom.xml +++ b/maven-resolver-transport-file/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-transport-file diff --git a/maven-resolver-transport-file/src/main/java/org/eclipse/aether/transport/file/FileTransporterFactory.java b/maven-resolver-transport-file/src/main/java/org/eclipse/aether/transport/file/FileTransporterFactory.java index 1b4753295..168cb9734 100644 --- a/maven-resolver-transport-file/src/main/java/org/eclipse/aether/transport/file/FileTransporterFactory.java +++ b/maven-resolver-transport-file/src/main/java/org/eclipse/aether/transport/file/FileTransporterFactory.java @@ -31,8 +31,9 @@ /** * A transporter factory for repositories using the {@code file:} protocol. */ -@Named("file") +@Named(FileTransporterFactory.NAME) public final class FileTransporterFactory implements TransporterFactory { + public static final String NAME = "file"; private float priority; diff --git a/maven-resolver-transport-http/pom.xml b/maven-resolver-transport-http/pom.xml index 82930f44a..928c8305b 100644 --- a/maven-resolver-transport-http/pom.xml +++ b/maven-resolver-transport-http/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-transport-http @@ -34,20 +34,9 @@ org.apache.maven.resolver.transport.http ${Automatic-Module-Name} - 9.4.51.v20230217 + 9.4.52.v20230823 - - - - - commons-codec - commons-codec - 1.15 - - - - org.apache.maven.resolver @@ -71,6 +60,11 @@ commons-logging commons-logging + + + commons-codec + commons-codec + @@ -78,6 +72,12 @@ httpcore 4.4.16 + + commons-codec + commons-codec + 1.16.0 + runtime + org.slf4j jcl-over-slf4j diff --git a/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java b/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java index 3fba6a911..870204747 100644 --- a/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java +++ b/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java @@ -31,10 +31,13 @@ import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.FileTime; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -43,12 +46,14 @@ import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpHeaders; import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.auth.AuthSchemeProvider; import org.apache.http.auth.AuthScope; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.HttpResponseException; +import org.apache.http.client.ServiceUnavailableRetryStrategy; import org.apache.http.client.config.AuthSchemes; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; @@ -75,6 +80,7 @@ import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.StandardHttpRequestRetryHandler; +import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; import org.eclipse.aether.ConfigurationProperties; import org.eclipse.aether.RepositorySystemSession; @@ -146,6 +152,7 @@ final class HttpTransporter extends AbstractTransporter { private final boolean supportWebDav; + @SuppressWarnings("checkstyle:methodlength") HttpTransporter( Map checksumExtractors, RemoteRepository repository, @@ -229,6 +236,21 @@ final class HttpTransporter extends AbstractTransporter { ConfigurationProperties.DEFAULT_HTTP_RETRY_HANDLER_COUNT, ConfigurationProperties.HTTP_RETRY_HANDLER_COUNT + "." + repository.getId(), ConfigurationProperties.HTTP_RETRY_HANDLER_COUNT); + long retryInterval = ConfigUtils.getLong( + session, + ConfigurationProperties.DEFAULT_HTTP_RETRY_HANDLER_INTERVAL, + ConfigurationProperties.HTTP_RETRY_HANDLER_INTERVAL + "." + repository.getId(), + ConfigurationProperties.HTTP_RETRY_HANDLER_INTERVAL); + long retryIntervalMax = ConfigUtils.getLong( + session, + ConfigurationProperties.DEFAULT_HTTP_RETRY_HANDLER_INTERVAL_MAX, + ConfigurationProperties.HTTP_RETRY_HANDLER_INTERVAL_MAX + "." + repository.getId(), + ConfigurationProperties.HTTP_RETRY_HANDLER_INTERVAL_MAX); + String serviceUnavailableCodesString = ConfigUtils.getString( + session, + ConfigurationProperties.DEFAULT_HTTP_RETRY_HANDLER_SERVICE_UNAVAILABLE, + ConfigurationProperties.HTTP_RETRY_HANDLER_SERVICE_UNAVAILABLE + "." + repository.getId(), + ConfigurationProperties.HTTP_RETRY_HANDLER_SERVICE_UNAVAILABLE); String retryHandlerName = ConfigUtils.getString( session, HTTP_RETRY_HANDLER_NAME_STANDARD, @@ -268,11 +290,24 @@ final class HttpTransporter extends AbstractTransporter { throw new IllegalArgumentException( "Unsupported parameter " + HTTP_RETRY_HANDLER_NAME + " value: " + retryHandlerName); } + Set serviceUnavailableCodes = new HashSet<>(); + try { + for (String code : ConfigUtils.parseCommaSeparatedUniqueNames(serviceUnavailableCodesString)) { + serviceUnavailableCodes.add(Integer.parseInt(code)); + } + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + "Illegal HTTP codes for " + ConfigurationProperties.HTTP_RETRY_HANDLER_SERVICE_UNAVAILABLE + + " (list of integers): " + serviceUnavailableCodesString); + } + ServiceUnavailableRetryStrategy serviceUnavailableRetryStrategy = new ResolverServiceUnavailableRetryStrategy( + retryCount, retryInterval, retryIntervalMax, serviceUnavailableCodes); HttpClientBuilder builder = HttpClientBuilder.create() .setUserAgent(userAgent) .setDefaultSocketConfig(socketConfig) .setDefaultRequestConfig(requestConfig) + .setServiceUnavailableRetryStrategy(serviceUnavailableRetryStrategy) .setRetryHandler(retryHandler) .setDefaultAuthSchemeRegistry(authSchemeRegistry) .setConnectionManager(state.getConnectionManager()) @@ -641,6 +676,17 @@ public void handle(CloseableHttpResponse response) throws IOException, TransferC task.setDataFile(dataFile); } } + if (task.getDataFile() != null) { + Header lastModifiedHeader = + response.getFirstHeader(HttpHeaders.LAST_MODIFIED); // note: Wagon also does first not last + if (lastModifiedHeader != null) { + Date lastModified = DateUtils.parseDate(lastModifiedHeader.getValue()); + if (lastModified != null) { + Files.setLastModifiedTime( + task.getDataFile().toPath(), FileTime.fromMillis(lastModified.getTime())); + } + } + } extractChecksums(response); } @@ -692,4 +738,98 @@ public void writeTo(OutputStream os) throws IOException { } } } + + private static class ResolverServiceUnavailableRetryStrategy implements ServiceUnavailableRetryStrategy { + private final int retryCount; + + private final long retryInterval; + + private final long retryIntervalMax; + + private final Set serviceUnavailableHttpCodes; + + /** + * Ugly, but forced by HttpClient API {@link ServiceUnavailableRetryStrategy}: the calls for + * {@link #retryRequest(HttpResponse, int, HttpContext)} and {@link #getRetryInterval()} are done by same + * thread and are actually done from spot that are very close to each other (almost subsequent calls). + */ + private static final ThreadLocal RETRY_INTERVAL_HOLDER = new ThreadLocal<>(); + + private ResolverServiceUnavailableRetryStrategy( + int retryCount, long retryInterval, long retryIntervalMax, Set serviceUnavailableHttpCodes) { + if (retryCount < 0) { + throw new IllegalArgumentException("retryCount must be >= 0"); + } + if (retryInterval < 0L) { + throw new IllegalArgumentException("retryInterval must be >= 0"); + } + if (retryIntervalMax < 0L) { + throw new IllegalArgumentException("retryIntervalMax must be >= 0"); + } + this.retryCount = retryCount; + this.retryInterval = retryInterval; + this.retryIntervalMax = retryIntervalMax; + this.serviceUnavailableHttpCodes = requireNonNull(serviceUnavailableHttpCodes); + } + + @Override + public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) { + final boolean retry = executionCount <= retryCount + && (serviceUnavailableHttpCodes.contains( + response.getStatusLine().getStatusCode())); + if (retry) { + Long retryInterval = retryInterval(response, executionCount, context); + if (retryInterval != null) { + RETRY_INTERVAL_HOLDER.set(retryInterval); + return true; + } + } + RETRY_INTERVAL_HOLDER.remove(); + return false; + } + + /** + * Calculates retry interval in milliseconds. If {@link HttpHeaders#RETRY_AFTER} header present, it obeys it. + * Otherwise, it returns {@link this#retryInterval} long value multiplied with {@code executionCount} (starts + * from 1 and goes 2, 3,...). + * + * @return Long representing the retry interval as millis, or {@code null} if the request should be failed. + */ + private Long retryInterval(HttpResponse httpResponse, int executionCount, HttpContext httpContext) { + Long result = null; + Header header = httpResponse.getFirstHeader(HttpHeaders.RETRY_AFTER); + if (header != null && header.getValue() != null) { + String headerValue = header.getValue(); + if (headerValue.contains(":")) { // is date when to retry + Date when = DateUtils.parseDate(headerValue); // presumably future + if (when != null) { + result = Math.max(when.getTime() - System.currentTimeMillis(), 0L); + } + } else { + try { + result = Long.parseLong(headerValue) * 1000L; // is in seconds + } catch (NumberFormatException e) { + // fall through + } + } + } + if (result == null) { + result = executionCount * this.retryInterval; + } + if (result > retryIntervalMax) { + return null; + } + return result; + } + + @Override + public long getRetryInterval() { + Long ri = RETRY_INTERVAL_HOLDER.get(); + if (ri == null) { + return 0L; + } + RETRY_INTERVAL_HOLDER.remove(); + return ri; + } + } } diff --git a/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporterFactory.java b/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporterFactory.java index f11670485..8cd098b10 100644 --- a/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporterFactory.java +++ b/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporterFactory.java @@ -37,8 +37,10 @@ * A transporter factory for repositories using the {@code http:} or {@code https:} protocol. The provided transporters * support uploads to WebDAV servers and resumable downloads. */ -@Named("http") +@Named(HttpTransporterFactory.NAME) public final class HttpTransporterFactory implements TransporterFactory { + public static final String NAME = "http"; + private static Map getManuallyCreatedExtractors() { HashMap map = new HashMap<>(); map.put(Nexus2ChecksumExtractor.NAME, new Nexus2ChecksumExtractor()); diff --git a/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpServer.java b/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpServer.java index 0c46e31fa..29ff91a55 100644 --- a/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpServer.java +++ b/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpServer.java @@ -113,7 +113,7 @@ public enum ChecksumHeader { private final AtomicInteger connectionsToClose = new AtomicInteger(0); - private List logEntries = Collections.synchronizedList(new ArrayList()); + private List logEntries = Collections.synchronizedList(new ArrayList<>()); public String getHost() { return "localhost"; diff --git a/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java b/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java index 6341c1553..597b35787 100644 --- a/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java +++ b/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java @@ -102,6 +102,8 @@ private void newTransporter(String url) throws Exception { transporter = factory.newInstance(session, newRepo(url)); } + private static final long OLD_FILE_TIMESTAMP = 160660800000L; + @Before public void setUp() throws Exception { System.out.println("=== " + testName.getMethodName() + " ==="); @@ -110,6 +112,7 @@ public void setUp() throws Exception { repoDir = TestFileUtils.createTempDir(); TestFileUtils.writeString(new File(repoDir, "file.txt"), "test"); TestFileUtils.writeString(new File(repoDir, "dir/file.txt"), "test"); + TestFileUtils.writeString(new File(repoDir, "dir/oldFile.txt"), "oldTest", OLD_FILE_TIMESTAMP); TestFileUtils.writeString(new File(repoDir, "empty.txt"), ""); TestFileUtils.writeString(new File(repoDir, "some space.txt"), "space"); File resumable = new File(repoDir, "resume.txt"); @@ -293,6 +296,23 @@ public void testGet_ToFile() throws Exception { assertEquals("test", new String(listener.baos.toByteArray(), StandardCharsets.UTF_8)); } + @Test + public void testGet_ToFileTimestamp() throws Exception { + File file = TestFileUtils.createTempFile("failure"); + RecordingTransportListener listener = new RecordingTransportListener(); + GetTask task = new GetTask(URI.create("repo/dir/oldFile.txt")) + .setDataFile(file) + .setListener(listener); + transporter.get(task); + assertEquals("oldTest", TestFileUtils.readString(file)); + assertEquals(0L, listener.dataOffset); + assertEquals(7L, listener.dataLength); + assertEquals(1, listener.startedCount); + assertTrue("Count: " + listener.progressedCount, listener.progressedCount > 0); + assertEquals("oldTest", new String(listener.baos.toByteArray(), StandardCharsets.UTF_8)); + assertEquals(file.lastModified(), OLD_FILE_TIMESTAMP); + } + @Test public void testGet_EmptyResource() throws Exception { File file = TestFileUtils.createTempFile("failure"); diff --git a/maven-resolver-transport-wagon/pom.xml b/maven-resolver-transport-wagon/pom.xml index ad8cf54ca..bb37726d8 100644 --- a/maven-resolver-transport-wagon/pom.xml +++ b/maven-resolver-transport-wagon/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-transport-wagon diff --git a/maven-resolver-transport-wagon/src/main/java/org/eclipse/aether/transport/wagon/WagonTransporterFactory.java b/maven-resolver-transport-wagon/src/main/java/org/eclipse/aether/transport/wagon/WagonTransporterFactory.java index 5c6ebabeb..dcd354b89 100644 --- a/maven-resolver-transport-wagon/src/main/java/org/eclipse/aether/transport/wagon/WagonTransporterFactory.java +++ b/maven-resolver-transport-wagon/src/main/java/org/eclipse/aether/transport/wagon/WagonTransporterFactory.java @@ -36,8 +36,9 @@ * that this factory merely serves as an adapter to the Wagon API and by itself does not provide any transport services * unless one or more wagon implementations are registered with the {@link WagonProvider}. */ -@Named("wagon") +@Named(WagonTransporterFactory.NAME) public final class WagonTransporterFactory implements TransporterFactory, Service { + public static final String NAME = "wagon"; private WagonProvider wagonProvider; @@ -50,12 +51,13 @@ public final class WagonTransporterFactory implements TransporterFactory, Servic * by clients, the new factory needs to be configured via its various mutators before first use or runtime errors * will occur. */ + @Deprecated public WagonTransporterFactory() { // enables default constructor } @Inject - WagonTransporterFactory(WagonProvider wagonProvider, WagonConfigurator wagonConfigurator) { + public WagonTransporterFactory(WagonProvider wagonProvider, WagonConfigurator wagonConfigurator) { setWagonProvider(wagonProvider); setWagonConfigurator(wagonConfigurator); } diff --git a/maven-resolver-util/pom.xml b/maven-resolver-util/pom.xml index 65cdef26d..4ef5e8e8c 100644 --- a/maven-resolver-util/pom.xml +++ b/maven-resolver-util/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT maven-resolver-util diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/artifact/ArtifactIdUtils.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/artifact/ArtifactIdUtils.java index 49901a73d..0d2a40180 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/artifact/ArtifactIdUtils.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/artifact/ArtifactIdUtils.java @@ -165,10 +165,7 @@ public static boolean equalsId(Artifact artifact1, Artifact artifact2) { if (!Objects.equals(artifact1.getClassifier(), artifact2.getClassifier())) { return false; } - if (!Objects.equals(artifact1.getVersion(), artifact2.getVersion())) { - return false; - } - return true; + return Objects.equals(artifact1.getVersion(), artifact2.getVersion()); } /** @@ -196,10 +193,7 @@ public static boolean equalsBaseId(Artifact artifact1, Artifact artifact2) { if (!Objects.equals(artifact1.getClassifier(), artifact2.getClassifier())) { return false; } - if (!Objects.equals(artifact1.getBaseVersion(), artifact2.getBaseVersion())) { - return false; - } - return true; + return Objects.equals(artifact1.getBaseVersion(), artifact2.getBaseVersion()); } /** @@ -225,9 +219,6 @@ public static boolean equalsVersionlessId(Artifact artifact1, Artifact artifact2 if (!Objects.equals(artifact1.getExtension(), artifact2.getExtension())) { return false; } - if (!Objects.equals(artifact1.getClassifier(), artifact2.getClassifier())) { - return false; - } - return true; + return Objects.equals(artifact1.getClassifier(), artifact2.getClassifier()); } } diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/filter/ExclusionsDependencyFilter.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/filter/ExclusionsDependencyFilter.java index 12d745af3..8c6b18587 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/filter/ExclusionsDependencyFilter.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/filter/ExclusionsDependencyFilter.java @@ -65,11 +65,7 @@ public boolean accept(DependencyNode node, List parents) { id = dependency.getArtifact().getGroupId() + ':' + id; - if (excludes.contains(id)) { - return false; - } - - return true; + return !(excludes.contains(id)); } @Override diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/ExclusionDependencySelector.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/ExclusionDependencySelector.java index a9d5a7efb..a44e8c816 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/ExclusionDependencySelector.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/ExclusionDependencySelector.java @@ -90,10 +90,7 @@ private boolean matches(Exclusion exclusion, Artifact artifact) { if (!matches(exclusion.getExtension(), artifact.getExtension())) { return false; } - if (!matches(exclusion.getClassifier(), artifact.getClassifier())) { - return false; - } - return true; + return matches(exclusion.getClassifier(), artifact.getClassifier()); } private boolean matches(String pattern, String value) { diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/filter/PatternExclusionsDependencyFilterTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/filter/PatternExclusionsDependencyFilterTest.java index 3a716b390..e6d1c00e3 100644 --- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/filter/PatternExclusionsDependencyFilterTest.java +++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/filter/PatternExclusionsDependencyFilterTest.java @@ -177,11 +177,11 @@ public void acceptTestRange() { } private boolean dontAccept(DependencyNode node, String expression) { - return !new PatternExclusionsDependencyFilter(expression).accept(node, new LinkedList()); + return !new PatternExclusionsDependencyFilter(expression).accept(node, new LinkedList<>()); } private boolean dontAcceptVersionRange(DependencyNode node, String... expression) { return !new PatternExclusionsDependencyFilter(new GenericVersionScheme(), expression) - .accept(node, new LinkedList()); + .accept(node, new LinkedList<>()); } } diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/filter/PatternInclusionsDependencyFilterTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/filter/PatternInclusionsDependencyFilterTest.java index 3117a24ad..9b022d595 100644 --- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/filter/PatternInclusionsDependencyFilterTest.java +++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/filter/PatternInclusionsDependencyFilterTest.java @@ -169,11 +169,11 @@ public void acceptTestRange() { } public boolean accept(DependencyNode node, String expression) { - return new PatternInclusionsDependencyFilter(expression).accept(node, new LinkedList()); + return new PatternInclusionsDependencyFilter(expression).accept(node, new LinkedList<>()); } public boolean acceptVersionRange(DependencyNode node, String... expression) { return new PatternInclusionsDependencyFilter(new GenericVersionScheme(), expression) - .accept(node, new LinkedList()); + .accept(node, new LinkedList<>()); } } diff --git a/pom.xml b/pom.xml index c96433022..ea95b910e 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ org.apache.maven.resolver maven-resolver - 1.9.15-SNAPSHOT + 2.0.0-SNAPSHOT pom Maven Artifact Resolver @@ -58,6 +58,7 @@ maven-resolver-transport-file maven-resolver-transport-http maven-resolver-transport-wagon + maven-resolver-supplier maven-resolver-demos @@ -84,16 +85,19 @@ 8 + ${javaVersion} true ${surefire.redirectTestOutputToFile} resolver-archives/resolver-LATEST None - 0.3.5 - 5.1.0 + 0.9.0.M2 + 6.0.0 1.7.36 - [3.8.7,) - [1.8.0-362,) - 2023-07-20T09:56:17Z + + 3.9.5 + [3.8.8,) + [11.0.16,) + 2023-10-10T21:40:45Z @@ -148,6 +152,11 @@ maven-resolver-transport-wagon ${project.version} + + org.apache.maven.resolver + maven-resolver-supplier + ${project.version} + org.apache.maven.resolver maven-resolver-test-util @@ -297,6 +306,27 @@ + + org.apache.maven.plugins + maven-enforcer-plugin + + + enforce-bytecode-version + + enforce + + + + + ${maven.compiler.release} + test + + + true + + + + org.apache.maven.plugins maven-javadoc-plugin @@ -421,20 +451,6 @@ - - org.eclipse.sisu - sisu-maven-plugin - ${sisuVersion} - - - generate-index - - main-index - - process-classes - - - org.apache.rat apache-rat-plugin @@ -478,29 +494,54 @@ + + + com.diffplug.spotless + spotless-maven-plugin + 2.40.0 + + + + + + 2.38.0 + + + + config/maven-eclipse-importorder.txt + + + config/maven-header-plain.txt + + + + + false + + true + + + + true + + + - org.codehaus.mojo - animal-sniffer-maven-plugin - 1.23 + org.apache.maven.plugins + maven-compiler-plugin - - org.codehaus.mojo.signature - java18 - 1.0 - + none + + -Xlint:deprecation + - - - check-java-compat - - check - - process-classes - - + + + org.eclipse.sisu + sisu-maven-plugin diff --git a/src/site/markdown/configuration.md b/src/site/markdown/configuration.md index 4f66f3f43..de1e60708 100644 --- a/src/site/markdown/configuration.md +++ b/src/site/markdown/configuration.md @@ -43,8 +43,11 @@ Option | Type | Description | Default Value | Supports Repo ID Suffix `aether.connector.http.preemptiveAuth` | boolean | Should HTTP client use preemptive-authentication for all HTTP verbs (works only w/ BASIC). By default is disabled, as it is considered less secure. | `false` | yes `aether.connector.http.preemptivePutAuth` | boolean | Should HTTP client use preemptive-authentication for HTTP PUTs only (works only w/ BASIC). By default is enabled (same as Wagon). | `true` | yes `aether.connector.http.retryHandler.count` | int | The maximum number of times a request to a remote HTTP server should be retried in case of an error. | `3` | yes +`aether.connector.http.retryHandler.interval` | long | The initial retry interval in milliseconds, if server responds with "too many requests". Is multiplied by 1, 2,.. on each try. If server emits `Retry-After` header, it is obeyed instead of this value. | `5000` | yes +`aether.connector.http.retryHandler.intervalMax` | long | The retry interval maximum in milliseconds, after request should be given up (5 minutes). | `300000` | yes `aether.connector.http.retryHandler.name` | String | The name of retryHandler, supported values are "standard", that obeys RFC-2616, regarding idempotent methods, and "default" that considers requests w/o payload as idempotent. | `standard` | yes `aether.connector.http.retryHandler.requestSentEnabled` | boolean | Set to `true` if it is acceptable to retry non-idempotent requests, that have been sent. | `false` | yes +`aether.connector.http.retryHandler.serviceUnavailable` | String | Comma separated list of HTTP codes that should be handled as "too many requests". | `"429,503"` | yes `aether.connector.http.reuseConnections` | boolean | Should HTTP client reuse connections (in other words, pool connections) or not? | `true` | yes `aether.connector.http.supportWebDav` | boolean | If enabled, transport makes best effort to deploy to WebDAV server. This mode is not recommended, better use real Maven Repository Manager instead. | `false` | yes `aether.connector.http.useSystemProperties` | boolean | If enabled, underlying Apache HttpClient will use system properties as well to configure itself (typically used to set up HTTP Proxy via Java system properties). See HttpClientBuilder for used properties. This mode is **not recommended**, better use documented ways of configuration instead. | `false` | yes @@ -61,7 +64,7 @@ Option | Type | Description | Default Value | Supports Repo ID Suffix `aether.connector.wagon.config` | Object | The configuration to use for the Wagon provider. | - | yes (must be used) `aether.dependencyCollector.maxCycles` | int | Only up to the given amount cyclic dependencies are emitted. | `10` | no `aether.dependencyCollector.maxExceptions` | int | Only exceptions up to the number given in this configuration property are emitted. Exceptions which exceed that number are swallowed. | `50` | no -`aether.dependencyCollector.impl` | String | The name of the dependency collector implementation to use: depth-first (original) named `df`, and breadth-first (new in 1.8.0) named `bf`. Both collectors produce equivalent results, but they may differ performance wise, depending on project being applied to. Our experience shows that existing `df` is well suited for smaller to medium size projects, while `bf` may perform better on huge projects with many dependencies. Experiment (and come back to us!) to figure out which one suits you the better. | `"df"` | no +`aether.dependencyCollector.impl` | String | The name of the dependency collector implementation to use: depth-first (original) named `df`, and breadth-first (new in 1.8.0) named `bf`. Both collectors produce equivalent results, but they may differ performance wise, depending on project being applied to. Our experience shows that existing `df` is well suited for smaller to medium size projects, while `bf` may perform better on huge projects with many dependencies. Experiment (and come back to us!) to figure out which one suits you the better. | `"bf"` | no `aether.dependencyCollector.bf.skipper` | boolean | Flag controlling whether to skip resolving duplicate/conflicting nodes during the breadth-first (`bf`) dependency collection process. | `true` | no `aether.dependencyCollector.bf.threads` or `maven.artifact.threads` | int | Number of threads to use for collecting POMs and version ranges in BF collector. | `5` | no `aether.dependencyCollector.pool.artifact` | String | Flag controlling interning data pool type used by dependency collector for Artifact instances, matters for heap consumption. By default uses "weak" references (consume less heap). Using "hard" will make it much more memory aggressive and possibly faster (system and Java dependent). Supported values: `"hard"`, `"weak"`. | `"weak"` | no diff --git a/src/site/markdown/third-party-integrations.md b/src/site/markdown/third-party-integrations.md new file mode 100644 index 000000000..d0e1d218b --- /dev/null +++ b/src/site/markdown/third-party-integrations.md @@ -0,0 +1,79 @@ +# Third-party integrations + + +Maven Resolver provided option for third-party integration using `ServiceLocator` (SL) +from the beginning. Back when SL was implemented, the DI container in use with Resolver and +Maven was the Plexus DI container, that had its own limitations: no constructor injection +among others. Hence, the two was somewhat aligned with each other. Today, with Sisu DI, +this is not true anymore: we want to use constructor injection for components, but +SL is always getting into our way forcing us to always add default constructor to components. +Hence, decision was made, and SL was deprecated while ago, and is about to be +dropped in Resolver 2.0.0 release. + +Resolver does provide alternative solution for those third-party integrations, where the +(recommended) Sisu DI is not available or cannot be used for some reason. All the +resolver integrations starting with release 1.9.15 can start migrating off the SL +to current solution described below. + +## Maven Resolver Supplier + +A new simple module `maven-resolver-supplier` serves the purpose to "bootstrap" resolver instance +when there is no desire to use [Eclipse Sisu](https://eclipse.dev/sisu/) DI. It provides one simple class +`org.eclipse.aether.supplier.RepositorySystemSupplier` that implements `Supplier` +and supplies new, ready-to-use `RepositorySystem` instance for each call. Class is intentionally simplistic, +no instance caching or anything alike is present: all that is concern of caller, just like proper shutdown +of the created resolver instances is. + +The `RepositorySystemSession` should be created using the +`org.apache.maven.repository.internal.MavenRepositorySystemUtils#newSession()` method +and local repository added to it in usual way (there is no change in this area). + +The supplier class is written in a way, to allow easy customization if needed: just extend the class and override +method as needed (all methods are protected). + +Consumer/users of this module **must provide SLF4J implementation** in classpath. Resolver uses `slf4j-api` for +logging purposes, but this module does NOT provide any implementation for it as a dependency. +It is the consumer/user obligation to provide one at runtime. + +Version of `maven-resolver-supplier` artifact in use **must be strictly aligned** with other Resolver artifacts +on classpath and Maven version. + +An example usage (and customization) of supplier can be seen in +[Maven Resolver Ant Tasks 1.5.0](https://github.com/apache/maven-resolver-ant-tasks/blob/maven-resolver-ant-tasks-1.5.0/src/main/java/org/apache/maven/resolver/internal/ant/AntRepositorySystemSupplier.java). + +## Resolver configuration + +By default, "full resolver experience" is provided: +* for connector, the connector-basic is provided +* for transport the two transport-file and transport-http implementations are provided. If Wagon is needed, add + transport-wagon as dependency (see Extending Resolver below). + +The supplier will provide fully usable instance. To configure resolver, use session user (or +configuration) properties, when constructing session. All the configuration options are available as +[listed here](https://maven.apache.org/resolver/configuration.html). + +## Extending Supplied Resolver + +Extending supplied resolver is simple, and basically requires same three steps for whatever extra you want to include +(like Wagon transport, distributed locking, etc). + +* First, you need to include needed module (with transitive deps) to your dependencies. +* Second, you need to customize `RepositorySystemSupplier` by extending it, and to make new components + available (by adding `WagonTransporterFactory` to transport factories, or distributed lock factories to lock factories). +* Third, you need to configure session (via user or configuration properties) to make Resolver use newly added components. + diff --git a/src/site/markdown/upgrading-resolver.md b/src/site/markdown/upgrading-resolver.md new file mode 100644 index 000000000..454bbbefb --- /dev/null +++ b/src/site/markdown/upgrading-resolver.md @@ -0,0 +1,26 @@ +# Upgrading Resolver (major versions) + + +This page will collect quick guides for developers upgrading from one to +another major version of Resolver. + +# Upgrading from 1.x to 2.x + +Maven Resolver upcoming major version 2.x should be "smooth sailing", as long you +do not depend (directly or indirectly) on **deprecated** classes from Resolver +1.x line. Always use latest 1.x release to check for deprecated classes. diff --git a/src/site/site.xml b/src/site/site.xml index 3dbe96ff5..d289dba5f 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -32,6 +32,8 @@ under the License. + +