diff --git a/maven-resolver-named-locks-hazelcast/pom.xml b/maven-resolver-named-locks-hazelcast/pom.xml
index 141f1c79e..b0c431ea8 100644
--- a/maven-resolver-named-locks-hazelcast/pom.xml
+++ b/maven-resolver-named-locks-hazelcast/pom.xml
@@ -45,7 +45,7 @@
com.hazelcasthazelcast
- 5.3.7
+ 5.3.8javax.inject
diff --git a/maven-resolver-named-locks-redisson/pom.xml b/maven-resolver-named-locks-redisson/pom.xml
index 703fa6eae..66016cb9d 100644
--- a/maven-resolver-named-locks-redisson/pom.xml
+++ b/maven-resolver-named-locks-redisson/pom.xml
@@ -31,10 +31,6 @@
Maven Artifact Resolver Named Locks using RedissonA synchronization utility implementation using Redisson.
-
- 1.20.1
-
-
org.apache.maven.resolver
@@ -49,7 +45,7 @@
org.redissonredisson
- 3.34.1
+ 3.37.0org.slf4j
@@ -120,7 +116,6 @@
org.apache.commonscommons-compress
- 1.27.1test
diff --git a/maven-resolver-tools/pom.xml b/maven-resolver-tools/pom.xml
index 443947c5a..5e71f077a 100644
--- a/maven-resolver-tools/pom.xml
+++ b/maven-resolver-tools/pom.xml
@@ -116,7 +116,7 @@
org.apache.velocityvelocity-engine-core
- 2.3
+ 2.4
diff --git a/maven-resolver-transport-minio/pom.xml b/maven-resolver-transport-minio/pom.xml
new file mode 100644
index 000000000..5ecd77801
--- /dev/null
+++ b/maven-resolver-transport-minio/pom.xml
@@ -0,0 +1,150 @@
+
+
+
+ 4.0.0
+
+
+ org.apache.maven.resolver
+ maven-resolver
+ 2.0.2-SNAPSHOT
+
+
+ maven-resolver-transport-minio
+ jar
+
+ Maven Artifact Resolver Transport S3 MinIO
+ Maven Artifact Transport S3 MinIO (Java).
+
+
+ 8
+
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+ org.apache.maven.resolver
+ maven-resolver-api
+
+
+ org.apache.maven.resolver
+ maven-resolver-spi
+
+
+ org.apache.maven.resolver
+ maven-resolver-util
+
+
+ javax.inject
+ javax.inject
+ provided
+ true
+
+
+
+ io.minio
+ minio
+ 8.5.11
+
+
+
+
+ commons-codec
+ commons-codec
+ 1.17.1
+ runtime
+
+
+ org.apache.commons
+ commons-compress
+ runtime
+
+
+ org.bouncycastle
+ bcprov-jdk18on
+ 1.78.1
+ runtime
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.slf4j
+ slf4j-simple
+ test
+
+
+ org.apache.maven.resolver
+ maven-resolver-test-util
+ test
+
+
+ org.apache.maven.resolver
+ maven-resolver-impl
+ test
+
+
+ org.testcontainers
+ testcontainers
+ ${testcontainersVersion}
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ ${testcontainersVersion}
+ test
+
+
+ org.testcontainers
+ minio
+ ${testcontainersVersion}
+ test
+
+
+
+
+
+
+ org.eclipse.sisu
+ sisu-maven-plugin
+
+
+
+
+
+
+ run-its
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+
+
+
diff --git a/maven-resolver-transport-minio/src/main/java/org/eclipse/aether/transport/minio/MinioTransporter.java b/maven-resolver-transport-minio/src/main/java/org/eclipse/aether/transport/minio/MinioTransporter.java
new file mode 100644
index 000000000..6556774f5
--- /dev/null
+++ b/maven-resolver-transport-minio/src/main/java/org/eclipse/aether/transport/minio/MinioTransporter.java
@@ -0,0 +1,207 @@
+/*
+ * 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.transport.minio;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import io.minio.GetObjectArgs;
+import io.minio.MinioClient;
+import io.minio.StatObjectArgs;
+import io.minio.UploadObjectArgs;
+import io.minio.credentials.Provider;
+import io.minio.credentials.StaticProvider;
+import io.minio.errors.ErrorResponseException;
+import org.eclipse.aether.ConfigurationProperties;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.repository.AuthenticationContext;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.spi.connector.transport.AbstractTransporter;
+import org.eclipse.aether.spi.connector.transport.GetTask;
+import org.eclipse.aether.spi.connector.transport.PeekTask;
+import org.eclipse.aether.spi.connector.transport.PutTask;
+import org.eclipse.aether.spi.connector.transport.Transporter;
+import org.eclipse.aether.transfer.NoTransporterException;
+import org.eclipse.aether.util.ConfigUtils;
+import org.eclipse.aether.util.FileUtils;
+
+/**
+ * A transporter for S3 backed by MinIO Java.
+ *
+ * @since 2.0.2
+ */
+final class MinioTransporter extends AbstractTransporter implements Transporter {
+ private final URI baseUri;
+
+ private final Map headers;
+
+ private final MinioClient client;
+
+ private final ObjectNameMapper objectNameMapper;
+
+ MinioTransporter(
+ RepositorySystemSession session,
+ RemoteRepository repository,
+ ObjectNameMapperFactory objectNameMapperFactory)
+ throws NoTransporterException {
+ try {
+ URI uri = new URI(repository.getUrl()).parseServerAuthority();
+ if (uri.isOpaque()) {
+ throw new URISyntaxException(repository.getUrl(), "URL must not be opaque");
+ }
+ if (uri.getRawFragment() != null || uri.getRawQuery() != null) {
+ throw new URISyntaxException(repository.getUrl(), "URL must not have fragment or query");
+ }
+ String path = uri.getPath();
+ if (path == null) {
+ path = "/";
+ }
+ if (!path.startsWith("/")) {
+ path = "/" + path;
+ }
+ if (!path.endsWith("/")) {
+ path = path + "/";
+ }
+ this.baseUri = URI.create(uri.getScheme() + "://" + uri.getRawAuthority() + path);
+ } catch (URISyntaxException e) {
+ throw new NoTransporterException(repository, e.getMessage(), e);
+ }
+
+ HashMap headers = new HashMap<>();
+ @SuppressWarnings("unchecked")
+ Map
diff --git a/src/site/markdown/configuration.md b/src/site/markdown/configuration.md
index c418b77b8..6c8f65eaa 100644
--- a/src/site/markdown/configuration.md
+++ b/src/site/markdown/configuration.md
@@ -132,17 +132,19 @@ under the License.
| 105. | `"aether.transport.jdk.maxConcurrentRequests"` | `Integer` | The hard limit of maximum concurrent requests JDK transport can do. This is a workaround for the fact, that in HTTP/2 mode, JDK HttpClient initializes this value to Integer.MAX_VALUE (!) and lowers it on first response from the remote server (but it may be too late). See JDK bug JDK-8225647 for details. | `100` | 2.0.0 | Yes | Session Configuration |
| 106. | `"aether.transport.jetty.followRedirects"` | `Boolean` | If enabled, Jetty client will follow HTTP redirects. | `true` | 2.0.1 | Yes | Session Configuration |
| 107. | `"aether.transport.jetty.maxRedirects"` | `Integer` | The max redirect count to follow. | `5` | 2.0.1 | Yes | Session Configuration |
-| 108. | `"aether.transport.wagon.config"` | `Object` | The configuration to use for the Wagon provider. | - | | Yes | Session Configuration |
-| 109. | `"aether.transport.wagon.perms.dirMode"` | `String` | Octal numerical notation of permissions to set for newly created directories. Only considered by certain Wagon providers. | - | | Yes | Session Configuration |
-| 110. | `"aether.transport.wagon.perms.fileMode"` | `String` | Octal numerical notation of permissions to set for newly created files. Only considered by certain Wagon providers. | - | | Yes | Session Configuration |
-| 111. | `"aether.transport.wagon.perms.group"` | `String` | Group which should own newly created directories/files. Only considered by certain Wagon providers. | - | | Yes | Session Configuration |
-| 112. | `"aether.trustedChecksumsSource.sparseDirectory"` | `Boolean` | Is checksum source enabled? | `false` | 1.9.0 | No | Session Configuration |
-| 113. | `"aether.trustedChecksumsSource.sparseDirectory.basedir"` | `String` | The basedir where checksums are. If relative, is resolved from local repository root. | `".checksums"` | 1.9.0 | No | Session Configuration |
-| 114. | `"aether.trustedChecksumsSource.sparseDirectory.originAware"` | `Boolean` | Is source origin aware? | `true` | 1.9.0 | No | Session Configuration |
-| 115. | `"aether.trustedChecksumsSource.summaryFile"` | `Boolean` | Is checksum source enabled? | `false` | 1.9.0 | No | Session Configuration |
-| 116. | `"aether.trustedChecksumsSource.summaryFile.basedir"` | `String` | The basedir where checksums are. If relative, is resolved from local repository root. | `".checksums"` | 1.9.0 | No | Session Configuration |
-| 117. | `"aether.trustedChecksumsSource.summaryFile.originAware"` | `Boolean` | Is source origin aware? | `true` | 1.9.0 | No | Session Configuration |
-| 118. | `"aether.updateCheckManager.sessionState"` | `String` | Manages the session state, i.e. influences if the same download requests to artifacts/metadata will happen multiple times within the same RepositorySystemSession. If "enabled" will enable the session state. If "bypass" will enable bypassing (i.e. store all artifact ids/metadata ids which have been updates but not evaluating those). All other values lead to disabling the session state completely. | `"enabled"` | | No | Session Configuration |
+| 108. | `"aether.transport.minio.fixedBucketName"` | `String` | The fixed bucket name to use. | `"maven"` | 2.0.2 | Yes | Session Configuration |
+| 109. | `"aether.transport.minio.objectNameMapper"` | `String` | Object name mapper to use. | `"fixedBucket"` | 2.0.2 | Yes | Session Configuration |
+| 110. | `"aether.transport.wagon.config"` | `Object` | The configuration to use for the Wagon provider. | - | | Yes | Session Configuration |
+| 111. | `"aether.transport.wagon.perms.dirMode"` | `String` | Octal numerical notation of permissions to set for newly created directories. Only considered by certain Wagon providers. | - | | Yes | Session Configuration |
+| 112. | `"aether.transport.wagon.perms.fileMode"` | `String` | Octal numerical notation of permissions to set for newly created files. Only considered by certain Wagon providers. | - | | Yes | Session Configuration |
+| 113. | `"aether.transport.wagon.perms.group"` | `String` | Group which should own newly created directories/files. Only considered by certain Wagon providers. | - | | Yes | Session Configuration |
+| 114. | `"aether.trustedChecksumsSource.sparseDirectory"` | `Boolean` | Is checksum source enabled? | `false` | 1.9.0 | No | Session Configuration |
+| 115. | `"aether.trustedChecksumsSource.sparseDirectory.basedir"` | `String` | The basedir where checksums are. If relative, is resolved from local repository root. | `".checksums"` | 1.9.0 | No | Session Configuration |
+| 116. | `"aether.trustedChecksumsSource.sparseDirectory.originAware"` | `Boolean` | Is source origin aware? | `true` | 1.9.0 | No | Session Configuration |
+| 117. | `"aether.trustedChecksumsSource.summaryFile"` | `Boolean` | Is checksum source enabled? | `false` | 1.9.0 | No | Session Configuration |
+| 118. | `"aether.trustedChecksumsSource.summaryFile.basedir"` | `String` | The basedir where checksums are. If relative, is resolved from local repository root. | `".checksums"` | 1.9.0 | No | Session Configuration |
+| 119. | `"aether.trustedChecksumsSource.summaryFile.originAware"` | `Boolean` | Is source origin aware? | `true` | 1.9.0 | No | Session Configuration |
+| 120. | `"aether.updateCheckManager.sessionState"` | `String` | Manages the session state, i.e. influences if the same download requests to artifacts/metadata will happen multiple times within the same RepositorySystemSession. If "enabled" will enable the session state. If "bypass" will enable bypassing (i.e. store all artifact ids/metadata ids which have been updates but not evaluating those). All other values lead to disabling the session state completely. | `"enabled"` | | No | Session Configuration |
All properties which have `yes` in the column `Supports Repo ID Suffix` can be optionally configured specifically for a repository id. In that case the configuration property needs to be suffixed with a period followed by the repository id of the repository to configure, e.g. `aether.connector.http.headers.central` for repository with id `central`.